Compare commits

...

41 Commits

Author SHA1 Message Date
Dmitriy Dolovov
6405270ad5 fix an issue with "lost" dependencies in project model when more than one KLIB is included into project's library 2018-08-17 15:30:45 +03:00
Dmitriy Dolovov
00ff4cedd0 safe creation of KonanBuiltIns when project model is broken or KLIBs are absent at the expected place 2018-08-17 14:50:18 +03:00
Dmitriy Dolovov
f16fefe8fa refactor KotlinWorkaroundUtil (Java -> Kotlin, drop unused methods, clean-up code) 2018-08-17 14:49:30 +03:00
Ilya Matveev
410f517ca2 Don't create compilation tasks for unsupported native targets 2018-08-17 16:35:15 +07:00
Dmitriy Dolovov
62b6d397ee Revert "read KLIB contents w/o IDEA file size limits (this does not fix the issue globally, but it does so for interop KLIBs)". This reverts commit d814895c47
Reason: The change applied in d814895c47 has no effect. The real fix for KT-24259 has been provided in commit dff8fde58d
2018-08-17 10:44:21 +03:00
Dmitriy Dolovov
dff8fde58d #KT-24259 Fixed 2018-08-16 16:05:38 +03:00
Ilya Matveev
14ff34b867 Use camel case in Kotlin/Native preset names 2018-08-16 19:29:02 +07:00
Ilya Matveev
3ac97ba810 Rename kotlin-native-utils -> konan-utils 2018-08-16 19:29:01 +07:00
Dmitriy Dolovov
84eada5a1b avoid exception when some KLIB that is expected on the file system accidentally disappears 2018-08-15 14:56:09 +03:00
Dmitriy Dolovov
260dab2c16 fix merge conflicts 2018-08-15 11:54:21 +03:00
Dmitriy Dolovov
d814895c47 read KLIB contents w/o IDEA file size limits (this does not fix the issue globally, but it does so for interop KLIBs) 2018-08-15 11:48:49 +03:00
Ilya Matveev
cab60784e3 Fix dependency on kotlin-native-utils in the Gradle plugin 2018-08-15 15:24:37 +07:00
Ilya Matveev
2975e6de7d Move native code into a separate project kotlin-native-utils 2018-08-15 15:24:36 +07:00
Ilya Matveev
dbf8482ec0 Support source set dependencies in native 2018-08-15 15:24:35 +07:00
Ilya Matveev
abf3efd08f Download KN compiler using Gradle's mechanisms 2018-08-15 15:24:34 +07:00
Ilya Matveev
94510a46ae Move targets from Kotlin/Native repo 2018-08-15 15:24:33 +07:00
Ilya Matveev
0465f61f63 Escape quotes in native command lines on Windows 2018-08-15 15:24:32 +07:00
Ilya Matveev
f58cb8a80c Mark code copied from Kotlin Native repo 2018-08-15 15:24:31 +07:00
Ilya Matveev
d01db12050 Basic support for Kotlin/Native
* Target presets
 * Compilation into a klib
 * Compilation into native binraies: framework and executable
 * Basic dependencies between projects
 * No jars in native publications
 * Replace '-' with '_' in framework names
2018-08-15 15:24:30 +07:00
Ilya Matveev
1f1a4dce4a Add dependency on KN shared in gradle-plugin 2018-08-15 15:24:29 +07:00
Dmitriy Dolovov
eccbd7a0b0 more correct initialization of KonanPlatformSupport 2018-08-14 16:29:36 +03:00
Dmitriy Dolovov
ebd861eee6 fix formatting 2018-08-14 16:16:42 +03:00
Dmitriy Dolovov
6514f15d4b more accurate work with klibs 2018-08-14 16:12:54 +03:00
Dmitriy Dolovov
eec7f64052 instruction for joint build 2018-08-14 15:00:21 +03:00
Dmitriy Dolovov
233d73781f instruction for joint build 2018-08-14 14:59:11 +03:00
Dmitriy Dolovov
8ed2bf0033 instruction for joint build 2018-08-14 14:57:46 +03:00
Dmitriy Dolovov
da997969ea [joint build][update] 1.2.70-dev-1218 2018-08-14 11:17:33 +03:00
Dmitriy Dolovov
fd4bff120a Kotlin/Native Plugin: Resolve cache error (disposed project)
#KT-25852 Fixed
2018-08-06 10:15:25 +03:00
Dmitriy Dolovov
2c46d9e67d K/N: Properly add modules for KLIBs generated by cinterop (with fixes) 2018-08-06 10:14:30 +03:00
Dmitriy Dolovov
ba6818e2d5 K/N: Properly add modules for KLIBs generated by cinterop 2018-08-06 10:14:18 +03:00
Dmitriy Dolovov
d7ad003e6f Minor. Dictionary 2018-08-06 10:13:58 +03:00
Alexander Podkhalyuzin
98af477fa3 Added kotlin-ultimate repository. 2018-08-04 15:30:16 +03:00
Alexander Podkhalyuzin
52b55f225b Added kotlin-ultimate root 2018-08-04 11:47:48 +03:00
Alexander Podkhalyuzin
f976dc069d Fixed compatibility after update to new Konan/Kotlin 2018-08-04 11:07:52 +03:00
Alexander Podkhalyuzin
82428d574f Fixed joint build 2018-08-04 11:07:52 +03:00
Alexander Podkhalyuzin
2ee9e2539c Kotlin + Kotlin/Native joint build. Still requires polishing. Now works 2018-08-04 11:07:51 +03:00
Vyacheslav Karpukhin
edf4d0ca3e K/N: Using correct module when constructing the KonanAnalyzerFacade 2018-08-04 11:06:34 +03:00
Alexander Podkhalyuzin
17c9c53a6c Better setting for kotlin-native build 2018-08-04 11:06:34 +03:00
Alexander Podkhalyuzin
1a4a1c5faf Gradle plugin right buildnumber 2018-08-04 11:06:33 +03:00
Alexander Podkhalyuzin
ef2dc5372d Fixed compatibility with new Kotlin Native 2018-08-04 11:06:33 +03:00
Alexander Podkhalyuzin
2988894bfb Kotlin/Native support in IntelliJ IDEA 2018-08-04 11:06:32 +03:00
75 changed files with 3148 additions and 125 deletions

2
.gitignore vendored
View File

@@ -38,3 +38,5 @@ build/
.idea/compiler.xml
.idea/inspectionProfiles/profiles_settings.xml
.idea/.name
kotlin-native/
kotlin-ultimate/

8
.idea/dictionaries/dmitriy_dolovov.xml generated Normal file
View File

@@ -0,0 +1,8 @@
<component name="ProjectDictionaryState">
<dictionary name="dmitriy.dolovov">
<words>
<w>klib</w>
<w>konan</w>
</words>
</dictionary>
</component>

View File

@@ -15,6 +15,6 @@
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<method />
<method v="2" />
</configuration>
</component>

5
.idea/vcs.xml generated
View File

@@ -24,6 +24,7 @@
</component>
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
<mapping directory="$PROJECT_DIR$/kotlin-native" vcs="Git" />
<mapping directory="$PROJECT_DIR$/kotlin-ultimate" vcs="Git" />
</component>
</project>
</project>

19
README_JOINT_BUILD.md Normal file
View File

@@ -0,0 +1,19 @@
# Joint Kotlin Build
How to work with Kotlin joint build:
1. Switch to `native-support/master` branch:
- `git checkout native-support/master`
2. Download Kotlin/Native repository and place it into `kotlin-native` subdirectory:
- `git clone https://github.com/JetBrains/kotlin-native.git`
- `git checkout native-support/master`
3. Similarly for Ultimate repository - place it into `kotlin-ultimate`:
- `git clone ssh://git@jetbrains.team/kotlin-ultimate.git`
- `git checkout native-support/master`
4. Refresh dependencies for Kotlin/Native:
- `./gradlew :kotlin-native:dependencies:update`
5. Build Kotlin/Native (this step is not included into joint build, therefore you need to run it manually):
- `cd ./kotlin-native/`
- `./gradlew dist distPlatformLibs`
6. Build Kotlin/Native plugin with all necessary dependencies and run it in IDEA Community Edition:
- `./gradlew runIde`

View File

@@ -23,6 +23,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
@@ -99,11 +100,19 @@ repositories {
}
val cidrKotlinPlugin by configurations.creating
val appcodeKotlinPlugin by configurations.creating
val clionKotlinPlugin by configurations.creating
val kotlinNativeEnabled by extra(project.getBooleanProperty("kotlinNativeEnabled") ?: false)
dependencies {
bootstrapCompileCfg(kotlinDep("compiler-embeddable", bootstrapKotlinVersion))
cidrKotlinPlugin(project(":prepare:cidr-plugin", "runtimeJar"))
if (kotlinNativeEnabled) {
cidrKotlinPlugin(project(":prepare:cidr-plugin", "runtimeJar"))
appcodeKotlinPlugin(project(":prepare:appcode-plugin", "runtimeJar"))
clionKotlinPlugin(project(":prepare:clion-plugin", "runtimeJar"))
}
}
val commonBuildDir = File(rootDir, "build")
@@ -113,9 +122,13 @@ val distLibDir = "$distKotlinHomeDir/lib"
val commonLocalDataDir = "$rootDir/local"
val ideaSandboxDir = "$commonLocalDataDir/ideaSandbox"
val ideaUltimateSandboxDir = "$commonLocalDataDir/ideaUltimateSandbox"
val clionSandboxDir = "$commonLocalDataDir/clionSandbox"
val appcodeSandboxDir = "$commonLocalDataDir/appcodeSandbox"
val ideaPluginDir = "$distDir/artifacts/ideaPlugin/Kotlin"
val ideaUltimatePluginDir = "$distDir/artifacts/ideaUltimatePlugin/Kotlin"
val cidrPluginDir = "$distDir/artifacts/cidrPlugin/Kotlin"
val appcodePluginDir = "$distDir/artifacts/appcodePlugin/kotlinNative-appcode"
val clionPluginDir = "$distDir/artifacts/clionPlugin/kotlinNative-clion"
// TODO: use "by extra()" syntax where possible
extra["distLibDir"] = project.file(distLibDir)
@@ -123,9 +136,13 @@ extra["libsDir"] = project.file(distLibDir)
extra["commonLocalDataDir"] = project.file(commonLocalDataDir)
extra["ideaSandboxDir"] = project.file(ideaSandboxDir)
extra["ideaUltimateSandboxDir"] = project.file(ideaUltimateSandboxDir)
extra["clionSandboxDir"] = project.file(ideaSandboxDir)
extra["appcodeSandboxDir"] = project.file(ideaSandboxDir)
extra["ideaPluginDir"] = project.file(ideaPluginDir)
extra["ideaUltimatePluginDir"] = project.file(ideaUltimatePluginDir)
extra["cidrPluginDir"] = project.file(cidrPluginDir)
extra["appcodePluginDir"] = project.file(appcodePluginDir)
extra["clionPluginDir"] = project.file(clionPluginDir)
extra["isSonatypeRelease"] = false
extra["JDK_16"] = jdkPath("1.6")
@@ -157,6 +174,7 @@ extra["versions.robolectric"] = "3.1"
extra["versions.org.springframework"] = "4.2.0.RELEASE"
extra["versions.jflex"] = "1.7.0"
extra["versions.markdown"] = "0.1.25"
extra["versions.kotlin.native"] = "0.9-dev-2859"
val isTeamcityBuild = project.hasProperty("teamcity") || System.getenv("TEAMCITY_VERSION") != null
val intellijUltimateEnabled = project.getBooleanProperty("intellijUltimateEnabled") ?: isTeamcityBuild
@@ -422,6 +440,8 @@ tasks {
delete(ideaPluginDir)
delete(ideaUltimatePluginDir)
delete(cidrPluginDir)
delete(appcodePluginDir)
delete(clionPluginDir)
}
}
@@ -610,9 +630,19 @@ val zipPlugin by task<Zip> {
}
}
val cidrPlugin by task<Copy> {
fun cidrPlugin(product: String, pluginDir: String) = tasks.creating(Copy::class.java) {
if (!kotlinNativeEnabled) {
throw GradleException("CIDR plugins require kotlinNativeEnabled")
}
val prepareCidrPlugin = getTasksByName("cidrPlugin", true)
val prepareCurrentPlugin = (getTasksByName(product.toLowerCase() + "Plugin", true) - this)
prepareCurrentPlugin.forEach { it.mustRunAfter(prepareCidrPlugin) }
dependsOn(ideaPlugin)
into(cidrPluginDir)
dependsOn(prepareCidrPlugin)
dependsOn(prepareCurrentPlugin)
into(pluginDir)
from(ideaPluginDir) {
exclude("lib/kotlin-plugin.jar")
@@ -628,17 +658,18 @@ val cidrPlugin by task<Copy> {
exclude("lib/maven-ide.jar")
}
from(cidrKotlinPlugin) { into("lib") }
from(configurations[product.toLowerCase() + "KotlinPlugin"]) { into("lib") }
}
val zipCidrPlugin by task<Zip> {
fun zipCidrPlugin(product: String) = tasks.creating(Zip::class.java) {
val destPath = project.findProperty("pluginZipPath") as String?
?: "$distDir/artifacts/kotlin-plugin-$kotlinVersion-CIDR.zip"
?: "$distDir/artifacts/kotlinNative-plugin-$kotlinVersion-$product.zip"
val destFile = File(destPath)
destinationDir = destFile.parentFile
archiveName = destFile.name
from(cidrPlugin)
from(tasks[product.toLowerCase() + "Plugin"])
into("Kotlin")
setExecutablePermissions()
@@ -647,6 +678,12 @@ val zipCidrPlugin by task<Zip> {
}
}
val appcodePlugin by cidrPlugin("AppCode", appcodePluginDir)
val zipAppCodePlugin by zipCidrPlugin("AppCode")
val clionPlugin by cidrPlugin("CLion", clionPluginDir)
val zipCLionPlugin by zipCidrPlugin("CLion")
configure<IdeaModel> {
module {
excludeDirs = files(

View File

@@ -1,3 +1,12 @@
import java.net.URI
allprojects {
repositories {
maven {
url = URI("https://cache-redirector.jetbrains.com/maven-central")
}
}
}
buildscript {
val buildSrcKotlinVersion: String by extra(findProperty("buildSrc.kotlin.version")?.toString() ?: embeddedKotlinVersion)
@@ -57,6 +66,7 @@ rootProject.apply {
val isTeamcityBuild = project.hasProperty("teamcity") || System.getenv("TEAMCITY_VERSION") != null
val intellijUltimateEnabled by extra(project.getBooleanProperty("intellijUltimateEnabled") ?: isTeamcityBuild)
val intellijSeparateSdks by extra(project.getBooleanProperty("intellijSeparateSdks") ?: false)
val kotlinNativeEnabled by extra(project.getBooleanProperty("kotlinNativeEnabled") ?: false)
extra["intellijRepo"] = "https://www.jetbrains.com/intellij-repository"

View File

@@ -5,3 +5,5 @@ org.gradle.jvmargs=-Duser.country=US -Dkotlin.daemon.jvm.options=-Xmx1600m
#buildSrc.kotlin.repo=https://jcenter.bintray.com
#buildSrc.kotlin.version=1.1.50
kotlinNativeEnabled=true

View File

@@ -1,3 +1,9 @@
include "prepare-deps:android-dx",
"prepare-deps:intellij-sdk"
include 'shared'
include 'plugins'
project(':shared').projectDir = file("../kotlin-native/buildSrc/shared")
project(':plugins').projectDir = file("../kotlin-native/buildSrc/plugins")

View File

@@ -11,6 +11,10 @@ import org.gradle.kotlin.dsl.extra
import org.gradle.kotlin.dsl.project
import java.io.File
fun Project.isKotlinNativeEnabled(): Boolean {
return rootProject.hasProperty("kotlinNativeEnabled") &&
rootProject.property("kotlinNativeEnabled") == "true"
}
fun Project.commonDep(coord: String): String {
val parts = coord.split(':')
@@ -123,4 +127,4 @@ fun AbstractCopyTask.fromEmbeddedComponents() {
}
}
}
}
}

View File

@@ -13,7 +13,10 @@ dependencies {
}
sourceSets {
"main" { projectDefault() }
"main" {
projectDefault()
java.srcDirs("$rootDir/core/runtime.jvm/src") //todo: what's this?
}
"test" {}
}

View File

@@ -6,7 +6,11 @@ org.gradle.jvmargs=-Duser.country=US -Dkotlin.daemon.jvm.options=-Xmx1600m
kotlin.compiler.effectSystemEnabled=true
kotlin.compiler.newInferenceEnabled=true
kotlin.incremental=false
kotlinNativeEnabled=true
#maven.repository.mirror=http://repository.jetbrains.com/remote-repos/
#bootstrap.kotlin.repo=https://dl.bintray.com/kotlin/kotlin-dev
#bootstrap.kotlin.version=1.1.50-dev-1451
#signingRequired=true
# Kotlin Native Properties
buildKotlinVersion=1.2.50

View File

@@ -11,4 +11,5 @@ kotlin.incremental=false
#bootstrap.kotlin.version=1.1.50-dev-1451
#signingRequired=true
kotlinNativeEnabled=true
intellijUltimateEnabled=false

View File

@@ -11,5 +11,6 @@ kotlin.incremental=false
#bootstrap.kotlin.version=1.1.50-dev-1451
#signingRequired=true
kotlinNativeEnabled=true
intellijUltimateEnabled=false
intellijEnforceCommunitySdk=true
intellijEnforceCommunitySdk=true

View File

@@ -17,6 +17,10 @@ dependencies {
val ideaPluginDir: File by rootProject.extra
val ideaSandboxDir: File by rootProject.extra
val clionPluginDir: File by rootProject.extra
val clionSandboxDir: File by rootProject.extra
val appcodePluginDir: File by rootProject.extra
val appcodeSandboxDir: File by rootProject.extra
runIdeTask("runIde", ideaPluginDir, ideaSandboxDir) {
dependsOn(":dist", ":ideaPlugin")

View File

@@ -123,4 +123,4 @@ class KotlinScriptDependenciesClassFinder(project: Project,
private fun String.splitByLastDot(): Pair<String, String> {
return Pair(substringBeforeLast('.', missingDelimiterValue = ""), substringAfterLast('.'))
}
}
}

View File

@@ -0,0 +1,37 @@
plugins {
kotlin("jvm")
id("jps-compatible")
}
dependencies {
compile("org.jetbrains.kotlin:kotlin-native-shared")
compile(project(":kotlin-native:backend.native"))
compile("org.jetbrains.kotlin:kotlin-native-gradle-plugin")
compileOnly(project(":idea:idea-gradle"))
compileOnly(project(":idea:idea-native"))
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"))
}
sourceSets {
"main" { projectDefault() }
"test" { none() }
}
configureInstrumentation()

View File

@@ -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")
}
}

View File

@@ -0,0 +1,12 @@
package org.jetbrains.konan.gradle
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 looksLikeKotlinNativeProject(): Boolean {
//TODO not just any gradle project
return GradleSettings.getInstance(project).linkedProjectsSettings.isNotEmpty()
}
}

View File

@@ -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)
}
}
}
}
}
}

View File

@@ -0,0 +1,151 @@
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())
library.addPath(LibraryPathType.BINARY, if(isDirectory(path)) path.toAbsolutePath().toString() else path.toString())
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)
}
}

View File

@@ -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);
}
}
}
}

View File

@@ -0,0 +1,28 @@
plugins {
kotlin("jvm")
}
dependencies {
compile("org.jetbrains.kotlin:kotlin-native-shared")
compile(project(":kotlin-native:backend.native"))
compile(project(":idea"))
compile(project(":idea:idea-core"))
compile(project(":compiler:frontend"))
compileOnly(intellijDep())
}
sourceSets {
"main" {
projectDefault()
java.srcDirs("$rootDir/core/runtime.jvm/src")
}
"test" { none() }
}
configureInstrumentation()
runtimeJar {
archiveName = "native-ide.jar"
}

View File

@@ -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)
}
}
}
}

View File

@@ -0,0 +1,9 @@
package org.jetbrains.konan
import com.intellij.openapi.vfs.VirtualFile
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)

View File

@@ -0,0 +1,48 @@
package org.jetbrains.konan
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiFileFactory
import com.intellij.psi.SingleRootFileViewProvider
import com.intellij.psi.impl.PsiFileFactoryImpl
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.stubs.PsiFileStub
import com.intellij.testFramework.LightVirtualFile
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.decompiler.textBuilder.LoggingErrorReporter
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactoryService
fun createFileStub(project: Project, text: String): PsiFileStub<*> {
val virtualFile = LightVirtualFile("dummy.kt", KotlinFileType.INSTANCE, text)
virtualFile.language = KotlinLanguage.INSTANCE
SingleRootFileViewProvider.doNotCheckFileSizeLimit(virtualFile)
val psiFileFactory = PsiFileFactory.getInstance(project) as PsiFileFactoryImpl
val file = psiFileFactory.trySetupPsiForFile(virtualFile, KotlinLanguage.INSTANCE, false, false)!!
return KtStubElementTypes.FILE.builder.buildStubTree(file) as PsiFileStub<*>
}
fun createLoggingErrorReporter(log: Logger) = LoggingErrorReporter(log)
fun <M : ModuleInfo> destructModuleContent(moduleContent: ModuleContent<M>) =
moduleContent.syntheticFiles to moduleContent.moduleContentScope
fun <M : ModuleInfo> createDeclarationProviderFactory(
project: Project,
moduleContext: ModuleContext,
syntheticFiles: Collection<KtFile>,
moduleInfo: M,
globalSearchScope: GlobalSearchScope?
) = DeclarationProviderFactoryService.createDeclarationProviderFactory(
project,
moduleContext.storageManager,
syntheticFiles,
globalSearchScope!!,
moduleInfo
)

View File

@@ -0,0 +1,91 @@
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)
}
}

View File

@@ -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)
}
}

View File

@@ -0,0 +1,142 @@
package org.jetbrains.konan.analyser
import com.intellij.openapi.roots.ModuleRootManager
import com.intellij.openapi.roots.libraries.Library
import com.intellij.openapi.vfs.LocalFileSystem
import org.jetbrains.konan.analyser.index.KonanDescriptorManager
import org.jetbrains.konan.createDeclarationProviderFactory
import org.jetbrains.konan.destructModuleContent
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.impl.CompositePackageFragmentProvider
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.frontend.di.createContainerForLazyResolve
import org.jetbrains.kotlin.idea.caches.project.LibraryInfo
import org.jetbrains.kotlin.idea.caches.project.ModuleProductionSourceInfo
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 java.io.File
/**
* @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
): ResolverForModule {
val (syntheticFiles, moduleContentScope) = destructModuleContent(moduleContent)
val project = moduleContext.project
val declarationProviderFactory = createDeclarationProviderFactory(
project,
moduleContext,
syntheticFiles,
moduleContent.moduleInfo,
moduleContentScope
)
val container = createContainerForLazyResolve(
moduleContext,
declarationProviderFactory,
BindingTraceContext(),
targetPlatform,
TargetPlatformVersion.NoVersion,
targetEnvironment,
languageVersionSettings
)
val packageFragmentProvider = container.get<ResolveSession>().packageFragmentProvider
val moduleInfo = moduleContent.moduleInfo as? ModuleProductionSourceInfo
val module = moduleInfo?.let { it.module }
fun createLibraryDescriptor(library: Library): ModuleDescriptorImpl? {
val libraryInfo = LibraryInfo(project, library)
// "first" because normally any KLIB should have just one root
// "null" just for the case when KLIB accidentally disappeared from the expected location
val libraryPath = libraryInfo.getLibraryRoots().firstOrNull()
val virtualFile = libraryPath?.let { LocalFileSystem.getInstance().refreshAndFindFileByIoFile(File(it)) }
return if (virtualFile != null && virtualFile.exists()) {
val libraryDescriptor =
KonanDescriptorManager.getInstance().getCachedLibraryDescriptor(virtualFile, languageVersionSettings)
//todo: replace reflection by changes to kotlin-native?
libraryDescriptor.setField("capabilities") { oldValue ->
val capabilities = oldValue as Map<*, *>
val libraryInfo = LibraryInfo(project, library)
capabilities + Pair(ModuleInfo.Capability, libraryInfo)
}
libraryDescriptor
} else null
}
val libraryDescriptors = mutableListOf<ModuleDescriptorImpl>()
var stdlibDescriptor: ModuleDescriptorImpl? = null
if (module != null) {
ModuleRootManager.getInstance(module).orderEntries().forEachLibrary { library ->
createLibraryDescriptor(library)?.also {
libraryDescriptors.add(it)
if (library.name?.substringAfter(": ") == "stdlib") {
stdlibDescriptor = it
}
}
true // continue the loop while there are more libs
}
}
// Create a module for handling `cnames.structs` opaque declarations. It should be a singleton and the last dependency in the list.
val forwardDeclarationsDescriptor = createForwardDeclarationsModule(moduleContext.module.builtIns, moduleContext.storageManager)
for (libraryDescriptor in libraryDescriptors) {
libraryDescriptor.setField("dependencies") { null }
val dependencies = mutableListOf(libraryDescriptor)
if (stdlibDescriptor != null && stdlibDescriptor != libraryDescriptor) {
// don't add stdlib if it's in fact absent, or if it's the current library on the loop
dependencies.add(stdlibDescriptor!!)
}
dependencies.add(forwardDeclarationsDescriptor)
libraryDescriptor.setDependencies(dependencies)
}
val fragmentProviders = mutableListOf(packageFragmentProvider)
libraryDescriptors.mapTo(fragmentProviders) { it.packageFragmentProvider }
fragmentProviders.add(forwardDeclarationsDescriptor.packageFragmentProvider)
return ResolverForModule(CompositePackageFragmentProvider(fragmentProviders), container)
}
}
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)
}
}

View File

@@ -0,0 +1,59 @@
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 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.DefaultBuiltIns
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<*>? = null
override val platform: TargetPlatform
get() = KonanPlatform
override fun createBuiltIns(settings: PlatformAnalysisSettings, sdkContext: GlobalContextImpl) = createKonanBuiltIns(sdkContext)
override fun isModuleForPlatform(module: Module) = true
}
private fun createKonanBuiltIns(sdkContext: GlobalContextImpl): KotlinBuiltIns {
//todo: it depends on a random project's stdlib, propagate the actual project here
val stdlibFile = ProjectManager.getInstance().openProjects.asSequence().mapNotNull {
val stdlibPath = KonanPaths.getInstance(it).konanStdlib()?.toFile()
if (stdlibPath != null) LocalFileSystem.getInstance().refreshAndFindFileByIoFile(stdlibPath) else null
}.firstOrNull()
if (stdlibFile != null) {
val builtInsModule: ModuleDescriptorImpl =
KonanDescriptorManager.getInstance().getCachedLibraryDescriptor(stdlibFile, LanguageVersionSettingsImpl.DEFAULT)
val builtIns: KotlinBuiltIns = KonanBuiltIns(sdkContext.storageManager)
builtInsModule.setField("dependencies") { null }
builtInsModule.setDependencies(builtInsModule)
builtIns.builtInsModule = builtInsModule
return builtIns
}
return DefaultBuiltIns.Instance
}

View File

@@ -0,0 +1,62 @@
/*
* 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.konan.analyser.index
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.ApplicationComponent
import com.intellij.openapi.vfs.*
import com.intellij.util.containers.ContainerUtil.createConcurrentWeakValueMap
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
class KonanDescriptorManager : ApplicationComponent {
companion object {
private const val currentAbiVersion = 1
@JvmStatic
fun getInstance(): KonanDescriptorManager = ApplicationManager.getApplication().getComponent(KonanDescriptorManager::class.java)
}
private val descriptorCache = createConcurrentWeakValueMap<VirtualFile, ConcurrentMap<LanguageVersionSettings, ModuleDescriptorImpl>>()
private val protoCache = createConcurrentWeakValueMap<VirtualFile, KonanLinkData.LinkDataPackageFragment>()
fun getCachedLibraryDescriptor(virtualFile: VirtualFile, languageVersionSettings: LanguageVersionSettings): ModuleDescriptorImpl {
return descriptorCache.computeIfAbsent(virtualFile) {
createConcurrentWeakValueMap()
}.computeIfAbsent(languageVersionSettings) {
val reader = LibraryReaderImpl(File(virtualFile.path), currentAbiVersion)
reader.moduleDescriptor(languageVersionSettings)
}
}
fun getCachedPackageFragment(virtualFile: VirtualFile): KonanLinkData.LinkDataPackageFragment {
return protoCache.computeIfAbsent(virtualFile) {
val bytes = virtualFile.contentsToByteArray(false)
org.jetbrains.kotlin.backend.konan.serialization.parsePackageFragment(bytes)
}
}
override fun initComponent() {
VirtualFileManager.getInstance().addVirtualFileListener(object : VirtualFileListener {
override fun fileCreated(event: VirtualFileEvent) = invalidateCaches(event.file)
override fun fileDeleted(event: VirtualFileEvent) = invalidateCaches(event.file)
override fun fileMoved(event: VirtualFileMoveEvent) = invalidateCaches(event.file)
override fun contentsChanged(event: VirtualFileEvent) = invalidateCaches(event.file)
override fun propertyChanged(event: VirtualFilePropertyEvent) = invalidateCaches(event.file)
})
}
private fun invalidateCaches(virtualFile: VirtualFile) {
descriptorCache.remove(virtualFile)
protoCache.remove(virtualFile)
}
}

View File

@@ -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);
}
}

View File

@@ -0,0 +1,28 @@
package org.jetbrains.konan.analyser.index
import com.intellij.util.indexing.FileBasedIndex
import org.jetbrains.kotlin.idea.vfilefinder.KotlinFileIndexBase
import org.jetbrains.kotlin.name.FqName
class KonanMetaFileIndex
: KotlinFileIndexBase<KonanMetaFileIndex>(KonanMetaFileIndex::class.java) {
companion object {
private const val VERSION = 4
}
/*todo: check version?!*/
private val dataIndexer = indexer { fileContent ->
val fragment = KonanDescriptorManager.getInstance().getCachedPackageFragment(fileContent.file)
FqName(fragment.fqName)
}
// this is to express intention to index all Kotlin/Native metadata files irrespectively to file size
override fun getFileTypesWithSizeLimitNotApplicable() = listOf(KonanMetaFileType)
override fun getInputFilter() = FileBasedIndex.InputFilter { it.fileType === KonanMetaFileType }
override fun getIndexer() = dataIndexer
override fun getVersion() = VERSION
}

View File

@@ -0,0 +1,50 @@
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.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 = KonanDescriptorManager.getInstance().getCachedPackageFragment(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)
}

View File

@@ -0,0 +1,132 @@
/*
* 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.PsiManager
import com.intellij.psi.compiled.ClassFileDecompilers
import org.jetbrains.konan.KonanDecompiledFile
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.idea.decompiler.KotlinDecompiledFileViewProvider
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, ::readFileSafely)
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) =
KotlinDecompiledFileViewProvider(manager, file, physical) { provider -> KonanDecompiledFile(provider, ::buildDecompiledText) }
private fun readFileSafely(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 {
assert(virtualFile.fileType == fileType) { "Unexpected file type ${virtualFile.fileType}" }
val file = readFileSafely(virtualFile)
return when (file) {
is FileWithMetadata.Incompatible -> createIncompatibleAbiVersionDecompiledText(expectedBinaryVersion, file.version)
is FileWithMetadata.Compatible -> decompiledText(file, targetPlatform, serializerProtocol, flexibleTypeDeserializer, renderer)
null -> createIncompatibleAbiVersionDecompiledText(expectedBinaryVersion, invalidBinaryVersion)
}
}
}
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)
}

View File

@@ -0,0 +1,82 @@
/*
* 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.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,
KonanMetadataVersion.DEFAULT_INSTANCE,
containerSource = null,
components = deserializationComponents
) { emptyList() }
return membersScope.getContributedDescriptors().toList()
}
companion object {
private val LOG = Logger.getInstance(KonanMetadataDeserializerForDecompiler::class.java)
}
}

View File

@@ -0,0 +1,58 @@
/*
* 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.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
return when (file) {
is FileWithMetadata.Incompatible -> 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)
createFileStub(content.project, ktFileText.text)
}
}
}
}

View File

@@ -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, KonanMetadataVersion.DEFAULT_INSTANCE, classSource(classId))
}
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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
}

View File

@@ -0,0 +1,99 @@
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
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 in libraryPaths) {
fun createLibrary(vfs: VirtualFileSystem, rootPath: String) {
val root = vfs.refreshAndFindFileByPath(rootPath) ?: return
val library = libraryTable.createLibrary(path.fileName.toString())
val libraryModifiableModel = library.modifiableModel
libraryModifiableModel.addRoot(root, OrderRootType.CLASSES)
runWriteAction {
libraryModifiableModel.commit()
}
}
val libraryRootPath = path.toString()
val libraryRoot: VirtualFile = localFileSystem.refreshAndFindFileByPath(libraryRootPath) ?: continue
// use JAR FS if this is file (*.klib), otherwise - local FS
createLibrary(if (libraryRoot.isDirectory) localFileSystem else jarFileSystem, libraryRootPath)
}
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
}

View File

@@ -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>

View 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>

View File

@@ -3019,6 +3019,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/*)"/>

View File

@@ -3019,6 +3019,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/*)"/>

View File

@@ -3018,6 +3018,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/*)"/>

View File

@@ -0,0 +1,21 @@
plugins {
kotlin("jvm")
id("jps-compatible")
}
description = "Kotlin/Native utils"
jvmTarget = "1.6"
dependencies {
compile(projectDist(":kotlin-stdlib"))
}
sourceSets {
"main" { projectDefault() }
"test" {}
}
standardPublicJars()
publish()

View File

@@ -0,0 +1,54 @@
/*
* 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.konan
import java.io.Serializable
interface KonanVersion : Serializable {
val meta: MetaVersion
val major: Int
val minor: Int
val maintenance: Int
val build: Int
fun toString(showMeta: Boolean, showBuild: Boolean): String
companion object
}
data class KonanVersionImpl(
override val meta: MetaVersion = MetaVersion.DEV,
override val major: Int,
override val minor: Int,
override val maintenance: Int,
override val build: Int = -1
) : KonanVersion {
override fun toString(showMeta: Boolean, showBuild: Boolean) = buildString {
append(major)
append('.')
append(minor)
if (maintenance != 0) {
append('.')
append(maintenance)
}
if (showMeta) {
append('-')
append(meta.metaString)
}
if (showBuild && build != -1) {
append('-')
append(build)
}
}
private val isRelease: Boolean
get() = meta == MetaVersion.RELEASE
private val versionString by lazy { toString(!isRelease, !isRelease) }
override fun toString() = versionString
}

View File

@@ -0,0 +1,21 @@
/*
* 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.konan
/**
* https://en.wikipedia.org/wiki/Software_versioning
* scheme major.minor[.build[.revision]].
*/
enum class MetaVersion(val metaString: String) {
DEV("dev"),
EAP("eap"),
ALPHA("alpha"),
BETA("beta"),
RC1("rc1"),
RC2("rc2"),
RELEASE("release")
}

View File

@@ -0,0 +1,279 @@
/*
* 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.konan.target
import org.jetbrains.kotlin.konan.target.KonanTarget.*
import org.jetbrains.kotlin.konan.util.Named
enum class Family(val exeSuffix:String, val dynamicPrefix: String, val dynamicSuffix: String,
val staticPrefix: String, val staticSuffix: String) {
OSX ("kexe", "lib", "dylib", "lib", "a"),
IOS ("kexe", "lib", "dylib", "lib", "a"),
LINUX ("kexe", "lib", "so" , "lib", "a"),
MINGW ("exe" , "" , "dll" , "lib", "a"),
ANDROID ("so" , "lib", "so" , "lib", "a"),
WASM ("wasm", "" , "wasm" , "", "wasm"),
ZEPHYR ("o" , "lib", "a" , "lib", "a")
}
enum class Architecture(val bitness: Int) {
X64(64),
ARM64(64),
ARM32(32),
MIPS32(32),
MIPSEL32(32),
WASM32(32);
}
sealed class KonanTarget(override val name: String, val family: Family, val architecture: Architecture) : Named {
object ANDROID_ARM32 : KonanTarget( "android_arm32", Family.ANDROID, Architecture.ARM32)
object ANDROID_ARM64 : KonanTarget( "android_arm64", Family.ANDROID, Architecture.ARM64)
object IOS_ARM32 : KonanTarget( "ios_arm32", Family.IOS, Architecture.ARM32)
object IOS_ARM64 : KonanTarget( "ios_arm64", Family.IOS, Architecture.ARM64)
object IOS_X64 : KonanTarget( "ios_x64", Family.IOS, Architecture.X64)
object LINUX_X64 : KonanTarget( "linux_x64", Family.LINUX, Architecture.X64)
object MINGW_X64 : KonanTarget( "mingw_x64", Family.MINGW, Architecture.X64)
object MACOS_X64 : KonanTarget( "macos_x64", Family.OSX, Architecture.X64)
object LINUX_ARM32_HFP :KonanTarget( "linux_arm32_hfp", Family.LINUX, Architecture.ARM32)
object LINUX_MIPS32 : KonanTarget( "linux_mips32", Family.LINUX, Architecture.MIPS32)
object LINUX_MIPSEL32 : KonanTarget( "linux_mipsel32", Family.LINUX, Architecture.MIPSEL32)
object WASM32 : KonanTarget( "wasm32", Family.WASM, Architecture.WASM32)
// Tunable targets
class ZEPHYR(val subName: String, val genericName: String = "zephyr") :
KonanTarget("${genericName}_$subName", Family.ZEPHYR, Architecture.ARM32)
override fun toString() = name
}
fun hostTargetSuffix(host: KonanTarget, target: KonanTarget) =
if (target == host) host.name else "${host.name}-${target.name}"
enum class CompilerOutputKind {
PROGRAM {
override fun suffix(target: KonanTarget?) = ".${target!!.family.exeSuffix}"
},
DYNAMIC {
override fun suffix(target: KonanTarget?) = ".${target!!.family.dynamicSuffix}"
override fun prefix(target: KonanTarget?) = "${target!!.family.dynamicPrefix}"
},
STATIC {
override fun suffix(target: KonanTarget?) = ".${target!!.family.staticSuffix}"
override fun prefix(target: KonanTarget?) = "${target!!.family.staticPrefix}"
},
FRAMEWORK {
override fun suffix(target: KonanTarget?): String = ".framework"
},
LIBRARY {
override fun suffix(target: KonanTarget?) = ".klib"
},
BITCODE {
override fun suffix(target: KonanTarget?) = ".bc"
};
abstract fun suffix(target: KonanTarget? = null): String
open fun prefix(target: KonanTarget? = null): String = ""
}
interface TargetManager {
val target: KonanTarget
val targetName : String
fun list() : Unit
val hostTargetSuffix: String
val targetSuffix: String
}
/** */
interface SubTargetProvider {
fun availableSubTarget(genericName: String): List<String>
}
private class NoSubTargets: SubTargetProvider {
override fun availableSubTarget(genericName: String): List<String> = emptyList()
}
private class TargetManagerImpl(val userRequest: String?, val hostManager: HostManager): TargetManager {
override val target = determineCurrent()
override val targetName
get() = target.visibleName
override fun list() {
hostManager.enabled.forEach {
val isDefault = if (it == target) "(default)" else ""
val aliasList = HostManager.listAliases(it.visibleName).joinToString(", ")
println(String.format("%1$-30s%2$-10s%3\$s", "${it.visibleName}:", "$isDefault", aliasList))
}
}
fun determineCurrent(): KonanTarget {
return if (userRequest == null || userRequest == "host") {
HostManager.host
} else {
val resolvedAlias = HostManager.resolveAlias(userRequest)
hostManager.targets[hostManager.known(resolvedAlias)]!!
}
}
override val hostTargetSuffix get() = hostTargetSuffix(HostManager.host, target)
override val targetSuffix get() = target.name
}
open class HostManager(subtargetProvider: SubTargetProvider = NoSubTargets()) {
fun targetManager(userRequest: String? = null): TargetManager = TargetManagerImpl(userRequest, this)
// TODO: need a better way to enumerated predefined targets.
private val predefinedTargets = listOf(
KonanTarget.ANDROID_ARM32, ANDROID_ARM64,
IOS_ARM32, IOS_ARM64, IOS_X64,
LINUX_X64, LINUX_ARM32_HFP, LINUX_MIPS32, LINUX_MIPSEL32,
MINGW_X64,
MACOS_X64,
WASM32)
private val zephyrSubtargets = subtargetProvider.availableSubTarget("zephyr").map { ZEPHYR(it) }
private val configurableSubtargets = zephyrSubtargets
val targetValues: List<KonanTarget> by lazy {
predefinedTargets + configurableSubtargets
}
val targets = targetValues.associate{ it.visibleName to it }
fun toKonanTargets(names: Iterable<String>): List<KonanTarget> {
return names.map {
if (it == "host") HostManager.host
else targets[known(resolveAlias(it))]!!
}
}
fun known(name: String): String {
if (targets[name] == null) {
throw TargetSupportException("Unknown target: $name. Use -list_targets to see the list of available targets")
}
return name
}
fun targetByName(name: String): KonanTarget {
if (name == "host") return host
val target = targets[resolveAlias(name)]
if (target == null) throw TargetSupportException("Unknown target name: $name")
return target
}
val enabled: List<KonanTarget> by lazy {
when (host) {
KonanTarget.LINUX_X64 -> listOf(
KonanTarget.LINUX_X64,
KonanTarget.LINUX_ARM32_HFP,
KonanTarget.LINUX_MIPS32,
KonanTarget.LINUX_MIPSEL32,
KonanTarget.ANDROID_ARM32,
KonanTarget.ANDROID_ARM64,
KonanTarget.WASM32
) + zephyrSubtargets
KonanTarget.MINGW_X64 -> listOf(
KonanTarget.MINGW_X64,
KonanTarget.WASM32
) + zephyrSubtargets
KonanTarget.MACOS_X64 -> listOf(
KonanTarget.MACOS_X64,
KonanTarget.IOS_ARM32,
KonanTarget.IOS_ARM64,
KonanTarget.IOS_X64,
KonanTarget.ANDROID_ARM32,
KonanTarget.ANDROID_ARM64,
KonanTarget.WASM32
) + zephyrSubtargets
else ->
throw TargetSupportException("Unknown host platform: $host")
}
}
fun isEnabled(target: KonanTarget) = enabled.contains(target)
companion object {
fun host_os(): String {
val javaOsName = System.getProperty("os.name")
return when {
javaOsName == "Mac OS X" -> "osx"
javaOsName == "Linux" -> "linux"
javaOsName.startsWith("Windows") -> "windows"
else -> throw TargetSupportException("Unknown operating system: ${javaOsName}")
}
}
@JvmStatic
fun simpleOsName(): String {
val hostOs = host_os()
return if (hostOs == "osx") "macos" else hostOs
}
val jniHostPlatformIncludeDir: String
get() = when(host) {
KonanTarget.MACOS_X64 -> "darwin"
KonanTarget.LINUX_X64 -> "linux"
KonanTarget.MINGW_X64 ->"win32"
else -> throw TargetSupportException("Unknown host: $host.")
}
fun host_arch(): String {
val javaArch = System.getProperty("os.arch")
return when (javaArch) {
"x86_64" -> "x86_64"
"amd64" -> "x86_64"
"arm64" -> "arm64"
else -> throw TargetSupportException("Unknown hardware platform: ${javaArch}")
}
}
val host: KonanTarget = when (host_os()) {
"osx" -> KonanTarget.MACOS_X64
"linux" -> KonanTarget.LINUX_X64
"windows" -> KonanTarget.MINGW_X64
else -> throw TargetSupportException("Unknown host target: ${host_os()} ${host_arch()}")
}
val hostIsMac = (host == KonanTarget.MACOS_X64)
val hostIsLinux = (host == KonanTarget.LINUX_X64)
val hostIsMingw = (host == KonanTarget.MINGW_X64)
val hostSuffix get() = host.name
@JvmStatic
val hostName get() = host.name
val knownTargetTemplates = listOf("zephyr")
private val targetAliasResolutions = mapOf(
"linux" to "linux_x64",
"macbook" to "macos_x64",
"macos" to "macos_x64",
"imac" to "macos_x64",
"raspberrypi" to "linux_arm32_hfp",
"iphone32" to "ios_arm32",
"iphone" to "ios_arm64",
"ipad" to "ios_arm64",
"ios" to "ios_arm64",
"iphone_sim" to "ios_x64",
"mingw" to "mingw_x64"
)
private val targetAliases: Map<String, List<String>> by lazy {
val result = mutableMapOf<String, MutableList<String>>()
targetAliasResolutions.entries.forEach {
result.getOrPut(it.value, { mutableListOf() } ).add(it.key)
}
result
}
fun resolveAlias(request: String): String = targetAliasResolutions[request] ?: request
fun listAliases(target: String): List<String> = targetAliases[target] ?: emptyList()
}
}
class TargetSupportException (message: String = "", cause: Throwable? = null) : Exception(message, cause)

View File

@@ -0,0 +1,21 @@
/*
* 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.konan.util
import java.io.File
object DependencyDirectories {
val localKonanDir: File by lazy {
File(System.getenv("KONAN_DATA_DIR") ?: (System.getProperty("user.home") + File.separator + ".konan"))
}
@JvmStatic
val defaultDependenciesRoot: File
get() = localKonanDir.resolve("dependencies")
val defaultDependencyCacheDir: File
get() = localKonanDir.resolve("cache")
}

View File

@@ -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.konan.util
val <T : Enum<T>> T.visibleName get() = name.toLowerCase()
interface Named {
val name: String
val visibleName get() = name
}

View File

@@ -15,7 +15,8 @@ pill {
dependencies {
compile project(':kotlin-stdlib')
compile project('::konan:konan-utils')
compileOnly gradleApi()
compileOnly 'com.android.tools.build:gradle:0.4.2'
}

View File

@@ -12,8 +12,7 @@ import org.gradle.api.attributes.CompatibilityCheckDetails
import java.io.Serializable
enum class KotlinPlatformType: Named, Serializable {
common, jvm, js, androidJvm,
native; // TODO: split native into separate entries here or transform the enum to interface and implement entries in K/N
common, jvm, js, androidJvm, native;
override fun toString(): String = name
override fun getName(): String = name

View File

@@ -38,6 +38,7 @@ dependencies {
compileOnly project(':compiler:daemon-common')
compile project(':kotlin-stdlib')
compile project(':konan:konan-utils')
compileOnly project(':kotlin-reflect-api')
compileOnly project(':kotlin-android-extensions')
compileOnly project(':kotlin-build-common')

View File

@@ -102,7 +102,7 @@ class Android25ProjectHandler(kotlinConfigurationTools: KotlinConfigurationTools
override fun setUpDependencyResolution(variant: BaseVariant, compilation: KotlinJvmAndroidCompilation) {
val project = compilation.target.project
KotlinTargetConfigurator.defineConfigurationsForCompilation(compilation, compilation.target, project.configurations)
AbstractKotlinTargetConfigurator.defineConfigurationsForCompilation(compilation, compilation.target, project.configurations)
compilation.compileDependencyFiles = variant.compileConfiguration.apply {
usesPlatformOf(compilation.target)

View File

@@ -0,0 +1,162 @@
/*
* 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.target.HostManager
import org.jetbrains.kotlin.konan.target.KonanTarget
import org.jetbrains.kotlin.konan.util.DependencyDirectories
/** Copied from Kotlin/Native repository. */
// TODO: Rename to FQ names
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.setProperty(property: KotlinNativeProjectProperty, value: Any?) =
extensions.extraProperties.set(property.propertyName, value)
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")
private fun String.escapeQuotes() = replace("\"", "\\\"")
private fun List<Pair<String, String>>.escapeQuotesForWindows() =
if (HostManager.hostIsMingw) {
map { (key, value) -> key.escapeQuotes() to value.escapeQuotes() }
} else {
this
}
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.toString() }
.escapeQuotesForWindows()
.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", DependencyDirectories.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)

View File

@@ -437,7 +437,7 @@ internal abstract class AbstractKotlinPlugin(
project.configurations.getByName(kotlinTarget.apiElementsConfigurationName).usesPlatformOf(kotlinTarget)
project.configurations.getByName(kotlinTarget.runtimeElementsConfigurationName).usesPlatformOf(kotlinTarget)
kotlinTarget.compilations.all { compilation ->
KotlinTargetConfigurator.defineConfigurationsForCompilation(compilation, kotlinTarget, project.configurations)
AbstractKotlinTargetConfigurator.defineConfigurationsForCompilation(compilation, kotlinTarget, project.configurations)
}
}
}

View File

@@ -18,6 +18,8 @@ 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.DefaultPublishArtifact
import org.gradle.api.internal.plugins.DefaultArtifactPublicationSet
import org.gradle.api.internal.plugins.DslObject
import org.gradle.api.plugins.BasePlugin
import org.gradle.api.plugins.JavaBasePlugin
@@ -26,22 +28,26 @@ import org.gradle.api.tasks.testing.Test
import org.gradle.internal.cleanup.BuildOutputCleanupRegistry
import org.gradle.language.base.plugins.LifecycleBasePlugin
import org.gradle.language.jvm.tasks.ProcessResources
import org.gradle.nativeplatform.test.tasks.RunTestExecutable
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinOnlyTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.disambiguateName
import org.jetbrains.kotlin.gradle.plugin.mpp.defaultSourceSetName
import org.jetbrains.kotlin.gradle.plugin.mpp.*
import org.jetbrains.kotlin.gradle.plugin.sources.getSourceSetHierarchy
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
import org.jetbrains.kotlin.gradle.tasks.KonanCompilerDownloadTask
import org.jetbrains.kotlin.gradle.tasks.KotlinNativeCompile
import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
import org.jetbrains.kotlin.konan.target.HostManager
import java.io.File
import java.util.*
import java.util.concurrent.Callable
open class KotlinTargetConfigurator(
abstract class AbstractKotlinTargetConfigurator<KotlinTargetType : KotlinTarget>(
private val buildOutputCleanupRegistry: BuildOutputCleanupRegistry
) {
fun <KotlinCompilationType: KotlinCompilation> configureTarget(
target: KotlinOnlyTarget<KotlinCompilationType>
open fun configureTarget(
target: KotlinTargetType
) {
configureCompilationDefaults(target)
configureCompilations(target)
@@ -49,11 +55,12 @@ open class KotlinTargetConfigurator(
configureArchivesAndComponent(target)
configureTest(target)
configureBuild(target)
setCompatibilityOfAbstractCompileTasks(target.project)
}
private fun <KotlinCompilationType: KotlinCompilation> configureCompilations(platformTarget: KotlinOnlyTarget<KotlinCompilationType>) {
abstract fun configureArchivesAndComponent(target: KotlinTargetType)
protected fun configureCompilations(platformTarget: KotlinTargetType) {
val project = platformTarget.project
val main = platformTarget.compilations.create(KotlinCompilation.MAIN_COMPILATION_NAME)
@@ -75,7 +82,7 @@ open class KotlinTargetConfigurator(
}
private fun <KotlinCompilationType: KotlinCompilation> configureCompilationDefaults(target: KotlinOnlyTarget<KotlinCompilationType>) {
protected fun configureCompilationDefaults(target: KotlinTargetType) {
val project = target.project
target.compilations.all { compilation ->
@@ -94,49 +101,7 @@ open class KotlinTargetConfigurator(
}
}
private fun configureArchivesAndComponent(target: KotlinOnlyTarget<*>) {
val project = target.project
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 apiElementsConfiguration = project.configurations.getByName(target.apiElementsConfigurationName)
target.disambiguationClassifier?.let { jar.classifier = it }
// Workaround: adding the artifact during configuration seems to interfere with the Java plugin, which results into missing
// task dependency 'assemble -> jar' if the Java plugin is applied after this steps
project.afterEvaluate {
project.artifacts.add(Dependency.ARCHIVES_CONFIGURATION, jar) { jarArtifact ->
jarArtifact.builtBy(jar)
jarArtifact.type = ArtifactTypeDefinition.JAR_TYPE
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 -- do we need that too?
}
}
}
}
private fun addJar(configuration: Configuration, jarArtifact: PublishArtifact) {
val publications = configuration.outgoing
// Configure an implicit variant
publications.artifacts.add(jarArtifact)
publications.attributes.attribute(ArtifactAttributes.ARTIFACT_FORMAT, ArtifactTypeDefinition.JAR_TYPE)
}
private fun configureTest(target: KotlinTarget) {
protected fun configureTest(target: KotlinTarget) {
val testCompilation = target.compilations.getByName(KotlinCompilation.TEST_COMPILATION_NAME) as? KotlinCompilationToRunnableFiles
?: return // Otherwise, there is no runtime classpath
@@ -151,7 +116,7 @@ open class KotlinTargetConfigurator(
}
}
private fun configureResourceProcessing(
protected fun configureResourceProcessing(
compilation: KotlinCompilationWithResources,
resourceSet: FileCollection
) {
@@ -168,7 +133,7 @@ open class KotlinTargetConfigurator(
resourcesTask.from(resourceSet)
}
private fun createLifecycleTask(compilation: KotlinCompilation) {
protected fun createLifecycleTask(compilation: KotlinCompilation) {
val project = compilation.target.project
(compilation.output.classesDirs as ConfigurableFileCollection).from(project.files().builtBy(compilation.compileAllTaskName))
@@ -186,7 +151,7 @@ open class KotlinTargetConfigurator(
}
}
private fun defineConfigurationsForTarget(target: KotlinOnlyTarget<*>) {
protected fun defineConfigurationsForTarget(target: KotlinTargetType) {
val project = target.project
val configurations = project.configurations
@@ -243,7 +208,7 @@ open class KotlinTargetConfigurator(
defaultConfiguration.extendsFrom(runtimeElementsConfiguration).usesPlatformOf(target)
}
private fun configureBuild(target: KotlinOnlyTarget<*>) {
protected fun configureBuild(target: KotlinTargetType) {
val project = target.project
val testCompilation = target.compilations.getByName(KotlinCompilation.TEST_COMPILATION_NAME)
project.tasks.maybeCreate(buildNeededTaskName, DefaultTask::class.java).apply {
@@ -279,14 +244,6 @@ open class KotlinTargetConfigurator(
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 = ""
}
}
companion object {
const val buildNeededTaskName = "buildAllNeeded"
const val buildDependentTaskName = "buildAllDependents"
@@ -374,14 +331,260 @@ open class KotlinTargetConfigurator(
}
}
private val KotlinCompilation.deprecatedCompileConfigurationName: String
internal val KotlinCompilation.deprecatedCompileConfigurationName: String
get() = disambiguateName("compile")
private val KotlinCompilationToRunnableFiles.deprecatedRuntimeConfigurationName: String
internal val KotlinCompilationToRunnableFiles.deprecatedRuntimeConfigurationName: String
get() = disambiguateName("runtime")
}
}
open class KotlinTargetConfigurator<KotlinCompilationType: KotlinCompilation>(
buildOutputCleanupRegistry: BuildOutputCleanupRegistry
) : AbstractKotlinTargetConfigurator<KotlinOnlyTarget<KotlinCompilationType>>(buildOutputCleanupRegistry) {
override fun configureTarget(
target: KotlinOnlyTarget<KotlinCompilationType>
) {
super.configureTarget(target)
setCompatibilityOfAbstractCompileTasks(target.project)
}
override fun configureArchivesAndComponent(target: KotlinOnlyTarget<KotlinCompilationType>) {
val project = target.project
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 apiElementsConfiguration = project.configurations.getByName(target.apiElementsConfigurationName)
target.disambiguationClassifier?.let { jar.classifier = it }
// Workaround: adding the artifact during configuration seems to interfere with the Java plugin, which results into missing
// task dependency 'assemble -> jar' if the Java plugin is applied after this steps
project.afterEvaluate {
project.artifacts.add(Dependency.ARCHIVES_CONFIGURATION, jar) { jarArtifact ->
jarArtifact.builtBy(jar)
jarArtifact.type = ArtifactTypeDefinition.JAR_TYPE
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 -- do we need that too?
}
}
}
}
private fun addJar(configuration: Configuration, jarArtifact: PublishArtifact) {
val publications = configuration.outgoing
// Configure an implicit variant
publications.artifacts.add(jarArtifact)
publications.attributes.attribute(ArtifactAttributes.ARTIFACT_FORMAT, ArtifactTypeDefinition.JAR_TYPE)
}
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 = ""
}
}
}
open class KotlinNativeTargetConfigurator(
buildOutputCleanupRegistry: BuildOutputCleanupRegistry
) : AbstractKotlinTargetConfigurator<KotlinNativeTarget>(buildOutputCleanupRegistry) {
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 Project.createTestTask(compilation: KotlinNativeCompilation, testExecutableLinkTask: KotlinNativeCompile) {
val taskName = lowerCamelCaseName("run", compilation.name, compilation.target.name)
val testTask = 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.get().absolutePath
// TODO: Provide a normal test path!
outputDir = project.layout.buildDirectory.dir("test-results").get().asFile
onlyIf { testExecutableProperty.get().exists() }
inputs.file(testExecutableProperty)
dependsOn(testExecutableLinkTask)
dependsOnCompilerDownloading()
}
tasks.maybeCreate(LifecycleBasePlugin.CHECK_TASK_NAME).apply {
dependsOn(testTask)
}
}
private fun Project.createBinaryLinkTasks(compilation: KotlinNativeCompilation) = whenEvaluated {
val konanTarget = compilation.target.konanTarget
val buildTypes = compilation.buildTypes
val availableOutputKinds = compilation.outputKinds.filter { it.availableFor(konanTarget) }
val linkAll = project.tasks.maybeCreate(compilation.linkAllTaskName)
for (buildType in compilation.buildTypes) {
for (kind in availableOutputKinds) {
val compilerOutputKind = kind.compilerOutputKind
val compilationSuffix = compilation.name
val buildTypeSuffix = createDimensionSuffix(buildType.name, buildTypes)
val targetSuffix = compilation.target.name
val kindSuffix = kind.taskNameClassifier
val taskName = lowerCamelCaseName("link", compilationSuffix, buildTypeSuffix, kindSuffix, 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
if (outputKind == CompilerOutputKind.FRAMEWORK) {
outputs.dir(outputFile)
} else {
outputs.file(outputFile)
}
outputFile.set(provider {
val targetSubDirectory = compilation.target.disambiguationClassifier?.let { "$it/" }.orEmpty()
val buildTypeSubDirectory = buildType.name.toLowerCase()
val compilationName = compilation.compilationName
val prefix = compilerOutputKind.prefix(konanTarget)
val suffix = compilerOutputKind.suffix(konanTarget)
var filename = "$prefix$compilationName$suffix"
if (outputKind == CompilerOutputKind.FRAMEWORK) {
filename = filename.replace('-', '_')
}
File(project.buildDir, "bin/$targetSubDirectory$compilationName/$buildTypeSubDirectory/$filename")
})
dependsOnCompilerDownloading()
linkAll.dependsOn(this)
}
if (compilation.isTestCompilation &&
buildType == NativeBuildType.DEBUG &&
konanTarget == HostManager.host
) {
createTestTask(compilation, linkTask)
}
}
}
}
private fun Project.createKlibPublishableArtifact(compilation: KotlinNativeCompilation, compileTask: KotlinNativeCompile) {
val apiElements = configurations.getByName(compilation.target.apiElementsConfigurationName)
val klibArtifact = DefaultPublishArtifact(
compilation.name,
"klib",
"klib",
null,
Date(),
compileTask.outputFile.get(),
compileTask
)
compilation.target.disambiguationClassifier?.let { klibArtifact.classifier = it }
project.extensions.getByType(DefaultArtifactPublicationSet::class.java).addCandidate(klibArtifact)
with(apiElements.outgoing) {
artifacts.add(klibArtifact)
attributes.attribute(ArtifactAttributes.ARTIFACT_FORMAT, NativeArtifactFormat.KLIB)
}
}
private fun Project.createKlibCompilationTask(compilation: KotlinNativeCompilation) {
val compileTask = 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}'"
outputs.file(outputFile)
outputFile.set(provider {
val targetSubDirectory = compilation.target.disambiguationClassifier?.let { "$it/" }.orEmpty()
val classifier = 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$classifier.klib")
})
dependsOnCompilerDownloading()
compilation.output.tryAddClassesDir {
project.files(this.outputFile).builtBy(this)
}
}
project.tasks.getByName(compilation.compileAllTaskName).dependsOn(compileTask)
if (compilation.compilationName == KotlinCompilation.MAIN_COMPILATION_NAME) {
project.tasks.getByName(compilation.target.artifactsTaskName).apply {
dependsOn(compileTask)
dependsOn(compilation.linkAllTaskName)
}
project.tasks.getByName(LifecycleBasePlugin.ASSEMBLE_TASK_NAME).apply {
dependsOn(compileTask)
dependsOn(compilation.linkAllTaskName)
}
createKlibPublishableArtifact(compilation, compileTask)
}
}
override fun configureArchivesAndComponent(target: KotlinNativeTarget) = with(target.project) {
if (!HostManager().isEnabled(target.konanTarget)) {
return
}
tasks.create(target.artifactsTaskName)
target.compilations.all {
createKlibCompilationTask(it)
createBinaryLinkTasks(it)
}
}
private fun Task.dependsOnCompilerDownloading() =
dependsOn(KonanCompilerDownloadTask.KONAN_DOWNLOAD_TASK_NAME)
object NativeArtifactFormat {
const val KLIB = "org.jerbrains.kotlin.klib"
}
}
internal fun Project.usageByName(usageName: String): Usage =
if (isGradleVersionAtLeast(4, 0)) {
// `project.objects` is an API introduced in Gradle 4.0
@@ -394,5 +597,9 @@ internal fun Project.usageByName(usageName: String): Usage =
fun Configuration.usesPlatformOf(target: KotlinTarget): Configuration {
attributes.attribute(KotlinPlatformType.attribute, target.platformType)
// TODO: Provide an universal way to copy attributes from the target.
if (target is KotlinNativeTarget) {
attributes.attribute(KotlinNativeTarget.konanTargetAttribute, target.konanTarget.name)
}
return this
}

View File

@@ -3,15 +3,6 @@
* that can be found in the license/LICENSE.txt file.
*/
/*
* 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.
*/
/*
* 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
@@ -82,4 +73,25 @@ class KotlinJsCompilationFactory(
override fun create(name: String): KotlinJsCompilation =
KotlinJsCompilation(target, name, target.createCompilationOutput(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, target.createCompilationOutput(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)
}
}
}

View File

@@ -3,16 +3,6 @@
* that can be found in the license/LICENSE.txt file.
*/
/*
* 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.
*/
/*
* 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

View File

@@ -25,6 +25,7 @@ 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
internal val Project.multiplatformExtension get(): KotlinMultiplatformExtension? =
project.extensions.getByName("kotlin") as KotlinMultiplatformExtension
@@ -81,6 +82,9 @@ internal class KotlinMultiplatformPlugin(
add(KotlinJsTargetPreset(project, instantiator, fileResolver, buildOutputCleanupRegistry, kotlinPluginVersion))
add(KotlinAndroidTargetPreset(project, kotlinPluginVersion))
add(KotlinJvmWithJavaTargetPreset(project, kotlinPluginVersion))
HostManager().targets.forEach { _, target ->
add(KotlinNativeTargetPreset(target.presetName, project, target, buildOutputCleanupRegistry))
}
}
}

View File

@@ -33,6 +33,12 @@ class KotlinSoftwareComponent(
}
}
// At the moment all KN artifacts have JAVA_API usage.
// TODO: Replace it with a specific usage
object NativeUsage {
const val KOTLIN_KLIB = "kotlin-klib"
}
internal class KotlinPlatformUsageContext(
val project: Project,
val kotlinTarget: KotlinTarget,

View File

@@ -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
}

View File

@@ -3,16 +3,6 @@
* that can be found in the license/LICENSE.txt file.
*/
/*
* 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.
*/
/*
* 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
@@ -59,21 +49,30 @@ internal class DefaultKotlinDependencyHandler(
}
abstract class AbstractKotlinCompilation(
final override val target: KotlinTarget,
target: KotlinTarget,
override val compilationName: String
) : KotlinCompilation, HasKotlinDependencies {
// Don't declare this property in the constructor to avoid NPE
// when an overriding property of a subclass is accessed instead.
override val target: KotlinTarget = target
private val attributeContainer = HierarchyAttributeContainer(target.attributes)
override fun getAttributes(): AttributeContainer = attributeContainer
override val kotlinSourceSets: MutableSet<KotlinSourceSet> = mutableSetOf()
open fun addSourcesToCompileTask(sourceSet: KotlinSourceSet) {
(target.project.tasks.getByName(compileKotlinTaskName) as AbstractKotlinCompile<*>).source(sourceSet.kotlin)
}
override fun source(sourceSet: KotlinSourceSet) {
if (kotlinSourceSets.add(sourceSet)) {
with(target.project) {
whenEvaluated {
sourceSet.getSourceSetHierarchy().forEach { sourceSet ->
(target.project.tasks.getByName(compileKotlinTaskName) as AbstractKotlinCompile<*>).source(sourceSet.kotlin)
addSourcesToCompileTask(sourceSet)
// Use `forced = false` since `api`, `implementation`, and `compileOnly` may be missing in some cases like
// old Java & Android projects:
@@ -242,4 +241,67 @@ class KotlinCommonCompilation(
target: KotlinTarget,
name: String,
override val output: SourceSetOutput
) : AbstractKotlinCompilation(target, name)
) : AbstractKotlinCompilation(target, name)
class KotlinNativeCompilation(
override val target: KotlinNativeTarget,
name: String,
override val output: SourceSetOutput
) : AbstractKotlinCompilation(target, name) {
// A FileCollection containing source files from all source sets used by this compilation
// (taking into account dependencies between source sets). Used by both compilation
// and linking tasks.
// TODO: Move into the compilation task when the linking task does klib linking instead of compilation.
internal var allSources: FileCollection = target.project.files()
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>()
// Naming
override val compileDependencyConfigurationName: String
get() = lowerCamelCaseName(
target.disambiguationClassifier,
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME }.orEmpty(),
"compileKlibraries"
)
override val compileAllTaskName: String
get() = lowerCamelCaseName(
target.disambiguationClassifier,
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME }.orEmpty(),
"klibrary"
)
override fun addSourcesToCompileTask(sourceSet: KotlinSourceSet) {
allSources += sourceSet.kotlin
}
// TODO: Can we do it better?
companion object {
val DEBUG = NativeBuildType.DEBUG
val RELEASE = NativeBuildType.RELEASE
val EXECUTABLE = NativeOutputKind.EXECUTABLE
val FRAMEWORK = NativeOutputKind.FRAMEWORK
}
}

View File

@@ -10,9 +10,14 @@ import org.gradle.api.internal.file.FileResolver
import org.gradle.api.plugins.JavaPlugin
import org.gradle.internal.cleanup.BuildOutputCleanupRegistry
import org.gradle.internal.reflect.Instantiator
import org.jetbrains.kotlin.compilerRunner.*
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.tasks.AndroidTasksProvider
import org.jetbrains.kotlin.gradle.tasks.KonanCompilerDownloadTask
import org.jetbrains.kotlin.gradle.tasks.KonanCompilerDownloadTask.Companion.KONAN_DOWNLOAD_TASK_NAME
import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
import org.jetbrains.kotlin.konan.target.KonanTarget
abstract class KotlinOnlyTargetPreset<T : KotlinCompilation>(
protected val project: Project,
@@ -31,7 +36,7 @@ abstract class KotlinOnlyTargetPreset<T : KotlinCompilation>(
compilations = project.container(compilationFactory.itemClass, compilationFactory)
}
KotlinTargetConfigurator(buildOutputCleanupRegistry).configureTarget(result)
KotlinTargetConfigurator<T>(buildOutputCleanupRegistry).configureTarget(result)
result.compilations.all { compilation ->
buildCompilationProcessor(compilation).run()
@@ -184,7 +189,7 @@ class KotlinJvmWithJavaTargetPreset(
target.compilations.all { compilation ->
// Set up dependency resolution using platforms:
KotlinTargetConfigurator.defineConfigurationsForCompilation(compilation, target, project.configurations)
AbstractKotlinTargetConfigurator.defineConfigurationsForCompilation(compilation, target, project.configurations)
}
target.compilations.getByName("test").run {
@@ -200,4 +205,43 @@ class KotlinJvmWithJavaTargetPreset(
companion object {
const val PRESET_NAME = "jvmWithJava"
}
}
}
class KotlinNativeTargetPreset(
private val name: String,
val project: Project,
val konanTarget: KonanTarget,
private val buildOutputCleanupRegistry: BuildOutputCleanupRegistry
) : KotlinTargetPreset<KotlinNativeTarget> {
override fun getName(): String = name
private fun createCompilerDownloadingTask() = with(project) {
if (!hasProperty(KotlinNativeProjectProperty.KONAN_HOME)) {
setProperty(KotlinNativeProjectProperty.KONAN_HOME, KonanCompilerDownloadTask.compilerDirectory)
setProperty(KotlinNativeProjectProperty.DOWNLOAD_COMPILER, true)
}
tasks.maybeCreate(KONAN_DOWNLOAD_TASK_NAME, KonanCompilerDownloadTask::class.java)
}
override fun createTarget(name: String): KotlinNativeTarget {
val result = KotlinNativeTarget(project, konanTarget).apply {
targetName = name
disambiguationClassifier = name
val compilationFactory = KotlinNativeCompilationFactory(project, this)
compilations = project.container(compilationFactory.itemClass, compilationFactory)
}
createCompilerDownloadingTask()
KotlinNativeTargetConfigurator(buildOutputCleanupRegistry).configureTarget(result)
return result
}
}
internal val KonanTarget.presetName: String
get() = when(this) {
KonanTarget.ANDROID_ARM32 -> "androidNativeArm32"
KonanTarget.ANDROID_ARM64 -> "androidNativeArm64"
else -> lowerCamelCaseName(*this.name.split('_').toTypedArray())
}

View File

@@ -7,6 +7,7 @@ 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.Attribute
import org.gradle.api.attributes.AttributeContainer
import org.gradle.api.internal.component.UsageContext
import org.gradle.api.plugins.JavaPlugin
@@ -15,6 +16,7 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinCompilationToRunnableFiles
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
import org.jetbrains.kotlin.konan.target.KonanTarget
abstract class AbstractKotlinTarget (
override val project: Project
@@ -118,3 +120,25 @@ open class KotlinOnlyTarget<T : KotlinCompilation>(
override var disambiguationClassifier: String? = null
internal set
}
class KotlinNativeTarget(
project: Project,
val konanTarget: KonanTarget
) : KotlinOnlyTarget<KotlinNativeCompilation>(project, KotlinPlatformType.native) {
init {
attributes.attribute(konanTargetAttribute, konanTarget.name)
}
// TODO: Should binary files be output of a target or a compilation?
override val artifactsTaskName: String
get() = disambiguateName("link")
companion object {
val konanTargetAttribute = Attribute.of(
"org.jetbrains.kotlin.native.target",
String::class.java
)
}
}

View File

@@ -0,0 +1,238 @@
package org.jetbrains.kotlin.gradle.tasks
import org.gradle.api.DefaultTask
import org.gradle.api.artifacts.repositories.ArtifactRepository
import org.gradle.api.artifacts.repositories.IvyPatternRepositoryLayout
import org.gradle.api.file.FileCollection
import org.gradle.api.file.FileTree
import org.gradle.api.provider.Property
import org.gradle.api.tasks.*
import org.jetbrains.kotlin.compilerRunner.*
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeCompilation
import org.jetbrains.kotlin.konan.KonanVersion
import org.jetbrains.kotlin.konan.KonanVersionImpl
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.DependencyDirectories
import java.io.File
// TODO: It's just temporary tasks 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: FileCollection
@InputFiles
@SkipWhenEmpty
get() = compilation.allSources
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
val outputFile: Property<File> = project.objects.property(File::class.java)
// 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.get()
output.parentFile.mkdirs()
val args = mutableListOf<String>().apply {
addArg("-o", outputFile.get().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.files.map { it.absolutePath })
}
KonanCompilerRunner(project).run(args)
}
}
open class KonanCompilerDownloadTask : DefaultTask() {
internal companion object {
val simpleOsName: String = HostManager.simpleOsName()
val compilerDirectory: File
get() = DependencyDirectories.localKonanDir.resolve("kotlin-native-$simpleOsName-$compilerVersion")
// TODO: Support project property for Kotlin/Native compiler version
val compilerVersion: KonanVersion = KonanVersionImpl(MetaVersion.RELEASE, 0, 8, 2)
internal const val BASE_DOWNLOAD_URL = "https://download.jetbrains.com/kotlin/native/builds"
const val KONAN_DOWNLOAD_TASK_NAME = "checkNativeCompiler"
}
private val useZip = HostManager.hostIsMingw
private val archiveExtension
get() = if (useZip) {
"zip"
} else {
"tar.gz"
}
private fun archiveFileTree(archive: File): FileTree =
if (useZip) {
project.zipTree(archive)
} else {
project.tarTree(archive)
}
private fun setupRepo(url: String): ArtifactRepository {
return project.repositories.ivy { repo ->
repo.setUrl(url)
repo.layout("pattern") {
val layout = it as IvyPatternRepositoryLayout
layout.artifact("[artifact]-[revision].[ext]")
}
repo.metadataSources {
it.artifact()
}
}
}
private fun removeRepo(repo: ArtifactRepository) {
project.repositories.remove(repo)
}
private fun downloadAndExtract() {
val versionString = compilerVersion.toString()
val url = buildString {
append("$BASE_DOWNLOAD_URL/")
append(if (compilerVersion.meta == MetaVersion.DEV) "dev/" else "releases/")
append("$versionString/")
append(simpleOsName)
}
val repo = setupRepo(url)
val compilerDependency = project.dependencies.create(
mapOf(
"name" to "kotlin-native-$simpleOsName",
"version" to versionString,
"ext" to archiveExtension
)
)
val configuration = project.configurations.detachedConfiguration(compilerDependency)
val archive = configuration.files.single()
logger.info("Use Kotlin/Native compiler archive: ${archive.absolutePath}")
logger.lifecycle("Unpack Kotlin/Native compiler (version $versionString)...")
project.copy {
it.from(archiveFileTree(archive))
it.into(DependencyDirectories.localKonanDir)
}
removeRepo(repo)
}
@TaskAction
fun checkCompiler() {
if (!project.hasProperty(KotlinNativeProjectProperty.DOWNLOAD_COMPILER)) {
val konanHome = project.getProperty(KotlinNativeProjectProperty.KONAN_HOME)
logger.info("Use a user-defined compiler path: $konanHome")
} else {
if (!compilerDirectory.exists()) {
downloadAndExtract()
}
logger.info("Use Kotlin/Native distribution: $compilerDirectory")
}
}
}

View File

@@ -0,0 +1,94 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import com.github.jk1.tcdeps.KotlinScriptDslAdapter.teamcityServer
import com.github.jk1.tcdeps.KotlinScriptDslAdapter.tc
import org.gradle.kotlin.dsl.support.zipTo
apply {
plugin("kotlin")
}
plugins {
id("com.github.jk1.tcdeps") version "0.17"
}
repositories {
teamcityServer {
setUrl("http://buildserver.labs.intellij.net")
credentials {
username = "guest"
password = "guest"
}
}
}
val cidrPluginDir: File by rootProject.extra
val appcodePluginDir: File by rootProject.extra
val appcodeVersion = rootProject.extra["versions.appcode"] as String
val appcodeVersionRepo = rootProject.extra["versions.appcode.repo"] as String
val cidrPlugin by configurations.creating
val platformDepsZip by configurations.creating
val pluginXmlPath = "META-INF/plugin.xml"
val platformDepsJarName = "kotlinNative-platformDeps.jar"
// Do not rename, used in JPS importer
val projectsToShadow by extra(listOf(
":kotlin-ultimate:cidr-native",
":kotlin-ultimate:appcode-native"))
dependencies {
cidrPlugin(project(":prepare:cidr-plugin"))
platformDepsZip(tc("$appcodeVersionRepo:$appcodeVersion:OC-plugins/kotlinNative-platformDeps-$appcodeVersion.zip"))
}
val kotlinPluginXml by tasks.creating {
inputs.files(cidrPlugin)
outputs.files(fileFrom(buildDir, name, "META-INF/KotlinPlugin.xml"))
doFirst {
val pluginXmlText = zipTree(inputs.files.singleFile)
.matching { include(pluginXmlPath) }
.singleFile
.readText()
outputs.files.singleFile.writeText(pluginXmlText)
}
}
val jar = runtimeJar {
archiveName = "kotlin-plugin.jar"
dependsOn(cidrPlugin)
from(kotlinPluginXml) { into("META-INF") }
from {
zipTree(cidrPlugin.singleFile).matching {
exclude(pluginXmlPath)
}
}
for (p in projectsToShadow) {
dependsOn("$p:classes")
from(getSourceSetsFrom(p)["main"].output)
}
}
val platformDepsJar by task<Zip> {
archiveName = platformDepsJarName
val platformDepsJar = zipTree(platformDepsZip.singleFile).matching { include("**/$platformDepsJarName") }.singleFile
from(zipTree(platformDepsJar)) {
exclude(pluginXmlPath)
}
}
task<Copy>("appcodePlugin") {
into(appcodePluginDir)
from(cidrPluginDir) { exclude("lib/kotlin-plugin.jar") }
from(jar) { into("lib") }
from(platformDepsJar) { into("lib") }
from(zipTree(platformDepsZip.singleFile).files) {
exclude("**/$platformDepsJarName")
into("lib")
}
from(File(project(":kotlin-ultimate:appcode-native").projectDir, "templates")) { into("templates") }
}

View File

@@ -22,7 +22,7 @@ dependencies {
val pluginXml by tasks.creating {
val kotlinVersion = rootProject.extra["kotlinVersion"] as String
val pluginFullVersionNumber = findProperty("pluginVersion") as? String
?: "$kotlinVersion-CIDR"
?: "$kotlinVersion-CIDR"
inputs.property("pluginFullVersionNumber", pluginFullVersionNumber)
inputs.files(kotlinPlugin)
@@ -30,8 +30,8 @@ val pluginXml by tasks.creating {
doFirst {
val placeholderRegex = Regex(
"""<!-- CIDR-PLUGIN-PLACEHOLDER-START -->(.*)<!-- CIDR-PLUGIN-PLACEHOLDER-END -->""",
RegexOption.DOT_MATCHES_ALL)
"""<!-- CIDR-PLUGIN-PLACEHOLDER-START -->(.*)<!-- CIDR-PLUGIN-PLACEHOLDER-END -->""",
RegexOption.DOT_MATCHES_ALL)
val excludeRegex = Regex(
"""<!-- CIDR-PLUGIN-EXCLUDE-START -->(.*?)<!-- CIDR-PLUGIN-EXCLUDE-END -->""",
@@ -65,6 +65,5 @@ val jar = runtimeJar {
task<Copy>("cidrPlugin") {
into(cidrPluginDir)
from(ideaPluginDir) { exclude("lib/kotlin-plugin.jar") }
from(jar) { into("lib") }
}
}

View File

@@ -0,0 +1,92 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import com.github.jk1.tcdeps.KotlinScriptDslAdapter.teamcityServer
import com.github.jk1.tcdeps.KotlinScriptDslAdapter.tc
apply {
plugin("kotlin")
}
plugins {
id("com.github.jk1.tcdeps") version "0.17"
}
repositories {
teamcityServer {
setUrl("http://buildserver.labs.intellij.net")
credentials {
username = "guest"
password = "guest"
}
}
}
val cidrPluginDir: File by rootProject.extra
val clionPluginDir: File by rootProject.extra
val clionVersion = rootProject.extra["versions.clion"] as String
val clionVersionRepo = rootProject.extra["versions.clion.repo"] as String
val cidrPlugin by configurations.creating
val platformDepsZip by configurations.creating
val pluginXmlPath = "META-INF/plugin.xml"
val platformDepsJarName = "kotlinNative-platformDeps.jar"
// Do not rename, used in JPS importer
val projectsToShadow by extra(listOf(
":kotlin-ultimate:cidr-native",
":kotlin-ultimate:clion-native"))
dependencies {
cidrPlugin(project(":prepare:cidr-plugin"))
platformDepsZip(tc("$clionVersionRepo:$clionVersion:CL-plugins/kotlinNative-platformDeps-$clionVersion.zip"))
}
val kotlinPluginXml by tasks.creating {
inputs.files(cidrPlugin)
outputs.files(fileFrom(buildDir, name, "META-INF/KotlinPlugin.xml"))
doFirst {
val pluginXmlText = zipTree(inputs.files.singleFile)
.matching { include(pluginXmlPath) }
.singleFile
.readText()
outputs.files.singleFile.writeText(pluginXmlText)
}
}
val jar = runtimeJar {
archiveName = "kotlin-plugin.jar"
dependsOn(cidrPlugin)
from(kotlinPluginXml) { into("META-INF") }
from {
zipTree(cidrPlugin.singleFile).matching {
exclude(pluginXmlPath)
}
}
for (p in projectsToShadow) {
dependsOn("$p:classes")
from(getSourceSetsFrom(p)["main"].output)
}
}
val platformDepsJar by task<Zip> {
archiveName = platformDepsJarName
val platformDepsJar = zipTree(platformDepsZip.singleFile).matching { include("**/$platformDepsJarName") }.singleFile
from(zipTree(platformDepsJar)) {
exclude(pluginXmlPath)
}
}
task<Copy>("clionPlugin") {
into(clionPluginDir)
from(cidrPluginDir) { exclude("lib/kotlin-plugin.jar") }
from(jar) { into("lib") }
from(platformDepsJar) { into("lib") }
from(zipTree(platformDepsZip.singleFile).files) {
exclude("**/$platformDepsJarName")
into("lib")
}
}

View File

@@ -30,8 +30,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",
@@ -55,6 +57,9 @@ val sideJars by configurations.creating
dependencies {
packedJars(protobufFull())
packedJars(project(":core:builtins", configuration = "builtins"))
sideJars(projectDist(":kotlin-native:backend.native")) { isTransitive = false }
sideJars("org.jetbrains.kotlin:kotlin-native-gradle-plugin") { isTransitive = false }
sideJars("org.jetbrains.kotlin:kotlin-native-shared") { isTransitive = false }
sideJars(projectDist(":kotlin-script-runtime"))
sideJars(projectDist(":kotlin-stdlib"))
sideJars(projectDist(":kotlin-reflect"))

View File

@@ -49,6 +49,7 @@ include ":kotlin-build-common",
":js:js.translator",
":js:js.dce",
":js:js.tests",
":konan:konan-utils",
":jps-plugin",
":kotlin-jps-plugin",
":core:descriptors",
@@ -179,6 +180,34 @@ include ":kotlin-build-common",
':kotlin-noarg:plugin-marker',
":test-instrumenter"
def isIncludeNative = hasProperty("kotlinNativeEnabled") && kotlinNativeEnabled != 'false'
if (isIncludeNative) {
include ":idea:idea-native",
":idea:idea-gradle:native",
":kotlin-ultimate:cidr-native",
":kotlin-ultimate:appcode-native",
":kotlin-ultimate:clion-native",
":prepare:cidr-plugin",
":prepare:appcode-plugin",
":prepare:clion-plugin"
// native
include ':kotlin-native:dependencies'
include ':kotlin-native:backend.native'
include ':kotlin-native:Interop:Runtime'
include ':kotlin-native:Interop:StubGenerator'
include ':kotlin-native:Interop:Indexer'
include ':kotlin-native:libclangext'
include ':kotlin-native:llvmDebugInfoC'
include ':kotlin-native:common'
include ':kotlin-native:llvmDebugInfoC'
include ':kotlin-native:runtime'
include ':kotlin-native:Interop:JsRuntime'
includeBuild 'kotlin-native/shared'
includeBuild 'kotlin-native/tools/kotlin-native-gradle-plugin'
}
def isTeamcityBuild = hasProperty("teamcity") || System.getenv("TEAMCITY_VERSION") != null
def includeUltimate = hasProperty("intellijUltimateEnabled") && intellijUltimateEnabled != 'false'
if (isTeamcityBuild || includeUltimate) {
@@ -230,6 +259,7 @@ project(':compiler:ir.psi2ir').projectDir = "$rootDir/compiler/ir/ir.psi2ir" as
project(':compiler:ir.ir2cfg').projectDir = "$rootDir/compiler/ir/ir.ir2cfg" as File
project(':compiler:ir.backend.common').projectDir = "$rootDir/compiler/ir/backend.common" as File
project(':compiler:backend.js').projectDir = "$rootDir/compiler/ir/backend.js" as File
project(':konan:konan-utils').projectDir = "$rootDir/konan/utils" as File
project(':kotlin-jps-plugin').projectDir = "$rootDir/prepare/jps-plugin" as File
project(':idea:idea-android-output-parser').projectDir = "$rootDir/idea/idea-android/idea-android-output-parser" as File
project(':plugins:android-extensions-compiler').projectDir = "$rootDir/plugins/android-extensions/android-extensions-compiler" as File

View File

@@ -1,6 +1,10 @@
extra["versions.intellijSdk"] = "182.3684.101"
extra["versions.androidBuildTools"] = "r23.0.1"
extra["versions.idea.NodeJS"] = "181.3494.12"
extra["versions.appcode"] = "183.1193"
extra["versions.appcode.repo"] = "ijplatform_master_CIDR_AppCode_Installers"
extra["versions.clion"] = "183.1192"
extra["versions.clion.repo"] = "ijplatform_master_CIDR_CLion_Installers"
//extra["versions.androidStudioRelease"] = "3.1.0.5"
//extra["versions.androidStudioBuild"] = "173.4506631"