diff --git a/buildSrc/settings.gradle b/buildSrc/settings.gradle index 0005526984c..e9c3380a68d 100644 --- a/buildSrc/settings.gradle +++ b/buildSrc/settings.gradle @@ -23,6 +23,17 @@ if (flags.includeCidrPlugins) { logger.info("NOT including CIDR plugins in buildSrc/settings.gradle") } +if (flags.hasKotlinUltimate) { + logger.info("Including extension for IJ Ultimate in buildSrc/settings.gradle") + include ":prepare-deps:lldb-frontend" + include ":prepare-deps:native-debug-plugin" + project(":prepare-deps:lldb-frontend").projectDir = file("${flags.propertiesProvider.rootProjectDir}/kotlin-ultimate/buildSrc/prepare-deps/lldb-frontend") + project(":prepare-deps:native-debug-plugin").projectDir = file("${flags.propertiesProvider.rootProjectDir}/kotlin-ultimate/buildSrc/prepare-deps/native-debug-plugin") +} else { + logger.info("Not including extension for IJ Ultimate in buildSrc/settings.gradle") +} + + class LocalBuildPropertiesProvider { private Settings settings private Properties localProperties = new Properties() @@ -57,8 +68,11 @@ class LocalBuildProperties { boolean includeCidrPlugins + boolean hasKotlinUltimate + LocalBuildProperties(Settings settings) { propertiesProvider = new LocalBuildPropertiesProvider(settings) - includeCidrPlugins = propertiesProvider.getBoolean('cidrPluginsEnabled') && new File(propertiesProvider.rootProjectDir, 'kotlin-ultimate').exists() + hasKotlinUltimate = new File(propertiesProvider.rootProjectDir, 'kotlin-ultimate').exists() + includeCidrPlugins = propertiesProvider.getBoolean('cidrPluginsEnabled') && hasKotlinUltimate } } diff --git a/buildSrc/src/main/kotlin/buildProperties.kt b/buildSrc/src/main/kotlin/buildProperties.kt index e45b2815a22..fdd5997a875 100644 --- a/buildSrc/src/main/kotlin/buildProperties.kt +++ b/buildSrc/src/main/kotlin/buildProperties.kt @@ -57,9 +57,7 @@ class KotlinBuildProperties( val useBootstrapStdlib: Boolean get() = isInJpsBuildIdeaSync || getBoolean("kotlin.build.useBootstrapStdlib", false) - val kotlinUltimateExists: Boolean = propertiesProvider.rootProjectDir.resolve("kotlin-ultimate").exists() - - val includeCidrPlugins: Boolean = kotlinUltimateExists && getBoolean("cidrPluginsEnabled") + private val kotlinUltimateExists: Boolean = propertiesProvider.rootProjectDir.resolve("kotlin-ultimate").exists() val isTeamcityBuild: Boolean = getBoolean("teamcity") || System.getenv("TEAMCITY_VERSION") != null @@ -72,6 +70,10 @@ class KotlinBuildProperties( return kotlinUltimateExists && (explicitlyEnabled || isTeamcityBuild) } + val includeCidrPlugins: Boolean = kotlinUltimateExists && getBoolean("cidrPluginsEnabled") + + val includeUltimate: Boolean = kotlinUltimateExists && (isTeamcityBuild || intellijUltimateEnabled) + val postProcessing: Boolean get() = isTeamcityBuild || getBoolean("kotlin.build.postprocessing", true) val relocation: Boolean get() = postProcessing diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleProjectResolverExtension.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleProjectResolverExtension.kt index ca54662201e..41d20e83663 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleProjectResolverExtension.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleProjectResolverExtension.kt @@ -57,6 +57,8 @@ var DataNode.isHmpp by NotNullableCopyableDataNodeUserDataProperty(Key.create("IS_HMPP_MODULE"), false) var DataNode.platformPluginId by CopyableDataNodeUserDataProperty(Key.create("PLATFORM_PLUGIN_ID")) +var DataNode.kotlinNativeHome + by CopyableDataNodeUserDataProperty(Key.create("KOTLIN_NATIVE_HOME")) var DataNode.implementedModuleNames by NotNullableCopyableDataNodeUserDataProperty(Key.create>("IMPLEMENTED_MODULE_NAME"), emptyList()) // Project is usually the same during all import, thus keeping Map Project->Dependencies makes model a bit more complicated but allows to avoid future problems diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinMPPDataNodes.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinMPPDataNodes.kt index c0a0d7f03f4..716aa447e74 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinMPPDataNodes.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinMPPDataNodes.kt @@ -15,10 +15,7 @@ import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil import com.intellij.openapi.util.Key import com.intellij.util.containers.MultiMap import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments -import org.jetbrains.kotlin.gradle.KotlinModule -import org.jetbrains.kotlin.gradle.KotlinPlatform -import org.jetbrains.kotlin.gradle.KotlinPlatformContainer -import org.jetbrains.kotlin.gradle.KotlinPlatformContainerImpl +import org.jetbrains.kotlin.gradle.* import org.jetbrains.kotlin.idea.util.CopyableDataNodeUserDataProperty import org.jetbrains.plugins.gradle.util.GradleConstants import java.io.File @@ -59,6 +56,7 @@ class KotlinAndroidSourceSetData( class KotlinTargetData(name: String) : AbstractNamedData(GradleConstants.SYSTEM_ID, name) { var moduleIds: Set = emptySet() var archiveFile: File? = null + var konanArtifacts: Collection? = null companion object { val KEY = ExternalKey.create(KotlinTargetData::class.java, ProjectKeys.MODULE.processingWeight + 1) diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinMPPGradleProjectResolver.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinMPPGradleProjectResolver.kt index 2bd584a0002..0e0061bd291 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinMPPGradleProjectResolver.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinMPPGradleProjectResolver.kt @@ -206,6 +206,8 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtension() { val mppModel = resolverCtx.getMppModel(gradleModule) if (mppModel == null || externalProject == null) return + mainModuleNode.kotlinNativeHome = mppModel.kotlinNativeHome + val jdkName = gradleModule.jdkNameIfAny // save artefacts locations. @@ -244,6 +246,7 @@ open class KotlinMPPGradleProjectResolver : AbstractProjectResolverExtension() { if (target.name == KotlinTarget.METADATA_TARGET_NAME) continue val targetData = KotlinTargetData(target.name).also { it.archiveFile = target.jar?.archiveFile + it.konanArtifacts = target.konanArtifacts } val targetDataNode = mainModuleNode.createChild(KotlinTargetData.KEY, targetData) diff --git a/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModel.kt b/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModel.kt index ea33eda3edc..7429ecdd659 100644 --- a/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModel.kt +++ b/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModel.kt @@ -119,7 +119,7 @@ enum class KotlinPlatform(val id: String) { } } -interface KotlinPlatformContainer: Serializable { +interface KotlinPlatformContainer : Serializable { val platforms: Collection fun supports(simplePlatform: KotlinPlatform): Boolean @@ -142,6 +142,7 @@ interface KotlinTarget : Serializable { val compilations: Collection val testTasks: Collection val jar: KotlinTargetJar? + val konanArtifacts: List companion object { const val METADATA_TARGET_NAME = "metadata" @@ -167,4 +168,29 @@ interface KotlinMPPGradleModel : Serializable { companion object { const val NO_KOTLIN_NATIVE_HOME = "" } -} \ No newline at end of file +} + +interface KonanArtifactModel : Serializable { + val targetName: String + val executableName: String + val type: String // represents org.jetbrains.kotlin.konan.target.CompilerOutputKind + val targetPlatform: String + val file: File + val buildTaskPath: String + val runConfiguration: KonanRunConfigurationModel + val isTests: Boolean +} + +interface KonanRunConfigurationModel : Serializable { + val workingDirectory: String + val programParameters: List + val environmentVariables: Map + + fun isNotEmpty() = workingDirectory.isNotEmpty() || programParameters.isNotEmpty() || environmentVariables.isNotEmpty() + + companion object { + const val NO_WORKING_DIRECTORY = "" + val NO_PROGRAM_PARAMETERS = emptyList() + val NO_ENVIRONMENT_VARIABLES = emptyMap() + } +} diff --git a/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt b/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt index ad62e926dd6..e6b5582ea56 100644 --- a/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt +++ b/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelBuilder.kt @@ -13,6 +13,8 @@ import org.gradle.api.file.FileCollection import org.gradle.api.file.SourceDirectorySet import org.gradle.api.logging.Logging import org.gradle.api.provider.Property +import org.gradle.api.provider.Provider +import org.gradle.api.tasks.Exec import org.jetbrains.kotlin.gradle.KotlinMPPGradleModel.Companion.NO_KOTLIN_NATIVE_HOME import org.jetbrains.plugins.gradle.model.* import org.jetbrains.plugins.gradle.tooling.ErrorMessageBuilder @@ -218,6 +220,53 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService { return project.getTargets()?.mapNotNull { buildTarget(it, sourceSetMap, dependencyResolver, project, dependencyMapper) } } + private operator fun Any?.get(methodName: String, vararg params: Any): Any? { + return this[methodName, params.map { it.javaClass }, params.toList()] + } + + private operator fun Any?.get(methodName: String, paramTypes: List>, params: List): Any? { + if (this == null) return null + return this::class.java.getMethodOrNull(methodName, *paramTypes.toTypedArray())?.invoke(this, *params.toTypedArray()) + } + + private fun buildArtifact( + executableName: String, + linkTask: Task, + runConfiguration: KonanRunConfigurationModel + ): KonanArtifactModel? { + val outputKind = linkTask["getOutputKind"]["name"] as? String ?: return null + val konanTargetName = linkTask["getTarget"] as? String ?: error("No arch target found") + val outputFile = (linkTask["getOutputFile"] as? Provider<*>)?.orNull as? File ?: return null + val compilationTarget = linkTask["getCompilation"]["getTarget"] + val compilationTargetName = compilationTarget["getName"] as? String ?: return null + val isTests = linkTask["getProcessTests"] as? Boolean ?: return null + + return KonanArtifactModelImpl( + compilationTargetName, + executableName, + outputKind, + konanTargetName, + outputFile, + linkTask.path, + runConfiguration, + isTests + ) + } + + private fun konanArtifacts(target: Named): List { + val result = ArrayList() + + val binaries = target["getBinaries"] as? Collection<*> ?: return result + binaries.forEach { binary -> + val executableName = binary["getBaseName"] as? String ?: "" + val linkTask = binary["getLinkTask"] as? Task ?: return@forEach + val runConfiguration = KonanRunConfigurationModelImpl(binary["getRunTask"] as? Exec) + buildArtifact(executableName, linkTask, runConfiguration)?.let { result.add(it) } + } + + return result + } + private fun buildTarget( gradleTarget: Named, sourceSetMap: Map, @@ -247,7 +296,17 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService { } val jar = buildTargetJar(gradleTarget, project) val testTasks = buildTestTasks(project, gradleTarget) - val target = KotlinTargetImpl(gradleTarget.name, targetPresetName, disambiguationClassifier, platform, compilations, testTasks, jar) + val artifacts = konanArtifacts(gradleTarget) + val target = KotlinTargetImpl( + gradleTarget.name, + targetPresetName, + disambiguationClassifier, + platform, + compilations, + testTasks, + jar, + artifacts + ) compilations.forEach { it.disambiguationClassifier = target.disambiguationClassifier it.platform = target.platform diff --git a/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelImpl.kt b/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelImpl.kt index cb28d556c70..04e658ad6e1 100644 --- a/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelImpl.kt +++ b/idea/kotlin-gradle-tooling/src/KotlinMPPGradleModelImpl.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.gradle +import org.gradle.api.tasks.Exec import java.io.File import kotlin.collections.HashSet @@ -133,7 +134,8 @@ data class KotlinTargetImpl( override val platform: KotlinPlatform, override val compilations: Collection, override val testTasks: Collection, - override val jar: KotlinTargetJar? + override val jar: KotlinTargetJar?, + override val konanArtifacts: List ) : KotlinTarget { override fun toString() = name @@ -152,7 +154,8 @@ data class KotlinTargetImpl( cloningCache[initialTestTask] = it } }, - KotlinTargetJarImpl(target.jar?.archiveFile) + KotlinTargetJarImpl(target.jar?.archiveFile), + target.konanArtifacts.map { KonanArtifactModelImpl(it) }.toList() ) } @@ -209,3 +212,44 @@ class KotlinPlatformContainerImpl() : KotlinPlatformContainer { (myPlatforms ?: HashSet().apply { myPlatforms = this }).addAll(platforms) } } + +data class KonanArtifactModelImpl( + override val targetName: String, + override val executableName: String, + override val type: String, + override val targetPlatform: String, + override val file: File, + override val buildTaskPath: String, + override val runConfiguration: KonanRunConfigurationModel, + override val isTests: Boolean +) : KonanArtifactModel { + constructor(artifact: KonanArtifactModel) : this( + artifact.targetName, + artifact.executableName, + artifact.type, + artifact.targetPlatform, + artifact.file, + artifact.buildTaskPath, + KonanRunConfigurationModelImpl(artifact.runConfiguration), + artifact.isTests + ) +} + +data class KonanRunConfigurationModelImpl( + override val workingDirectory: String, + override val programParameters: List, + override val environmentVariables: Map +) : KonanRunConfigurationModel { + constructor(configuration: KonanRunConfigurationModel) : this( + configuration.workingDirectory, + ArrayList(configuration.programParameters), + HashMap(configuration.environmentVariables) + ) + + constructor(runTask: Exec?) : this( + runTask?.workingDir?.path ?: KonanRunConfigurationModel.NO_WORKING_DIRECTORY, + runTask?.args as List? ?: KonanRunConfigurationModel.NO_PROGRAM_PARAMETERS, + (runTask?.environment as Map?) + ?.mapValues { it.value.toString() } ?: KonanRunConfigurationModel.NO_ENVIRONMENT_VARIABLES + ) +} diff --git a/idea/kotlin-gradle-tooling/src/KotlinNativeHomeEvaluator.kt b/idea/kotlin-gradle-tooling/src/KotlinNativeHomeEvaluator.kt index bfb0c0ba6c5..8bf01e49a7f 100644 --- a/idea/kotlin-gradle-tooling/src/KotlinNativeHomeEvaluator.kt +++ b/idea/kotlin-gradle-tooling/src/KotlinNativeHomeEvaluator.kt @@ -8,13 +8,13 @@ package org.jetbrains.kotlin.gradle import org.gradle.api.Project // KT-29613, KT-29783 -internal object KotlinNativeHomeEvaluator { +object KotlinNativeHomeEvaluator { private const val KOTLIN_NATIVE_HOME_PRIVATE_PROPERTY = "konanHome" private const val FALLBACK_ACCESSOR_CLASS = "org.jetbrains.kotlin.compilerRunner.KotlinNativeToolRunnerKt" private const val FALLBACK_ACCESSOR_METHOD = "getKonanHome" - internal fun getKotlinNativeHome(project: Project): String? = + fun getKotlinNativeHome(project: Project): String? = getKotlinNativeHomePrimary(project) ?: getKotlinNativeHomeFallback(project) // Read Kotlin/Native home from the predefined property in Gradle plugin. diff --git a/settings.gradle b/settings.gradle index ab3999a962a..828e3db9aca 100644 --- a/settings.gradle +++ b/settings.gradle @@ -226,7 +226,8 @@ def flags = BuildPropertiesKt.getKotlinBuildPropertiesForSettings(settings) if (flags.includeCidrPlugins) { logger.info("Including CIDR plugins in settings.gradle") - include ":kotlin-ultimate:ide:cidr-native", + include ":kotlin-ultimate:ide:common-native", + ":kotlin-ultimate:ide:cidr-native", ":kotlin-ultimate:ide:clion-native", ":kotlin-ultimate:ide:appcode-native", ":kotlin-ultimate:prepare:cidr-plugin", @@ -236,12 +237,11 @@ if (flags.includeCidrPlugins) { logger.info("NOT including CIDR plugins in settings.gradle") } -def isTeamcityBuild = hasProperty("teamcity") || System.getenv("TEAMCITY_VERSION") != null -if (flags.kotlinUltimateExists && (isTeamcityBuild || flags.intellijUltimateEnabled)) { - include( - ":kotlin-ultimate:ultimate", - ":kotlin-ultimate:ultimate:ultimate-runner" - ) +if (flags.includeUltimate) { + include ":kotlin-ultimate:ultimate", + ":kotlin-ultimate:ultimate:ultimate-runner", + ":kotlin-ultimate:ide:common-native", + ":kotlin-ultimate:ide:ultimate-native" logger.info("Including extension for IJ Ultimate in settings.gradle") } else { logger.info("NOT including extension for IJ Ultimate in settings.gradle")