diff --git a/idea/idea-gradle-native/src/org/jetbrains/kotlin/ide/konan/gradle/KotlinGradleNativeMultiplatformModuleBuilder.kt b/idea/idea-gradle-native/src/org/jetbrains/kotlin/ide/konan/gradle/KotlinGradleNativeMultiplatformModuleBuilder.kt new file mode 100644 index 00000000000..02c97baf11f --- /dev/null +++ b/idea/idea-gradle-native/src/org/jetbrains/kotlin/ide/konan/gradle/KotlinGradleNativeMultiplatformModuleBuilder.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.ide.konan.gradle + +import org.jetbrains.kotlin.idea.configuration.KotlinGradleAbstractMultiplatformModuleBuilder +import org.jetbrains.kotlin.konan.target.presetName + +class KotlinGradleNativeMultiplatformModuleBuilder : KotlinGradleAbstractMultiplatformModuleBuilder() { + + override fun getBuilderId() = "kotlin.gradle.multiplatform.native" + + override fun getPresentableName() = "Kotlin/Native" + + override fun getDescription() = "Kotlin module for native binaries" + + override val notImportedCommonSourceSets = true + + override fun buildMultiPlatformPart(): String { + return """ + kotlin { + targets { + // For ARM, preset should be changed to presets.iosArm32 or presets.iosArm64 + // For Linux, preset should be changed to e.g. presets.linuxX64 + // For MacOS, preset should be changed to e.g. presets.macosX64 + fromPreset(presets.${defaultNativeTarget.presetName}, '${defaultNativeTarget.userTargetName}') + } + } + """.trimIndent() + } +} diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/GradleKotlinFrameworkSupportProvider.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/GradleKotlinFrameworkSupportProvider.kt index 1dd77f4856e..f727c7cad0f 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/GradleKotlinFrameworkSupportProvider.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/GradleKotlinFrameworkSupportProvider.kt @@ -132,7 +132,7 @@ abstract class GradleKotlinFrameworkSupportProvider( val isNewProject = module.project.getUserData(ExternalSystemDataKeys.NEWLY_CREATED_PROJECT) == true if (isNewProject) { ProjectCodeStyleImporter.apply(module.project, KotlinStyleGuideCodeStyle.INSTANCE) - GradlePropertiesFileUtils.addCodeStyleProperty(module.project, KotlinStyleGuideCodeStyle.CODE_STYLE_SETTING) + GradlePropertiesFileFacade.forProject(module.project).addCodeStyleProperty(KotlinStyleGuideCodeStyle.CODE_STYLE_SETTING) } } diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/GradlePropertiesFileFacade.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/GradlePropertiesFileFacade.kt new file mode 100644 index 00000000000..b2acee739cc --- /dev/null +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/GradlePropertiesFileFacade.kt @@ -0,0 +1,67 @@ +/* + * 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.idea.configuration + +import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil +import com.intellij.openapi.project.Project +import com.intellij.openapi.vfs.LocalFileSystem +import org.jetbrains.plugins.gradle.model.ExternalProject +import java.io.File +import java.util.* + +internal class GradlePropertiesFileFacade(private val baseDir: String) { + + fun readProperty(propertyName: String): String? { + + val baseVirtualDir = LocalFileSystem.getInstance().findFileByPath(baseDir) ?: return null + + for (propertyFileName in GRADLE_PROPERTY_FILES) { + val propertyFile = baseVirtualDir.findChild(propertyFileName) ?: continue + Properties().also { it.load(propertyFile.inputStream) }.getProperty(propertyName)?.let { + return it + } + } + + return null + } + + fun addCodeStyleProperty(value: String) { + addProperty(KOTLIN_CODE_STYLE_GRADLE_SETTING, value) + } + + fun addNotImportedCommonSourceSetsProperty() { + addProperty(KOTLIN_NOT_IMPORTED_COMMON_SOURCE_SETS_SETTING, true.toString()) + } + + private fun addProperty(key: String, value: String) { + val projectPropertiesFile = File(baseDir, GRADLE_PROPERTIES_FILE_NAME) + + val keyValue = "$key=$value" + + val updatedText = if (projectPropertiesFile.exists()) { + projectPropertiesFile.readText() + System.lineSeparator() + keyValue + } else { + keyValue + } + + projectPropertiesFile.writeText(updatedText) + } + + companion object { + + fun forProject(project: Project) = GradlePropertiesFileFacade(ExternalSystemApiUtil.toCanonicalPath(project.basePath!!)) + + fun forExternalProject(externalProject: ExternalProject) = GradlePropertiesFileFacade(externalProject.projectDir.canonicalPath) + + const val KOTLIN_CODE_STYLE_GRADLE_SETTING = "kotlin.code.style" + const val KOTLIN_NOT_IMPORTED_COMMON_SOURCE_SETS_SETTING = "kotlin.import.noCommonSourceSets" + + private const val GRADLE_PROPERTIES_FILE_NAME = "gradle.properties" + private const val GRADLE_PROPERTIES_LOCAL_FILE_NAME = "local.properties" + + private val GRADLE_PROPERTY_FILES = listOf(GRADLE_PROPERTIES_LOCAL_FILE_NAME, GRADLE_PROPERTIES_FILE_NAME) + } +} \ No newline at end of file diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/GradlePropertiesFileUtils.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/GradlePropertiesFileUtils.kt deleted file mode 100644 index 4a808035ca2..00000000000 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/GradlePropertiesFileUtils.kt +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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.idea.configuration - -import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil -import com.intellij.openapi.project.Project -import java.io.File -import java.util.* - -internal object GradlePropertiesFileUtils { - const val KOTLIN_CODE_STYLE_GRADLE_SETTING = "kotlin.code.style" - - private const val GRADLE_PROPERTIES_FILE_NAME = "gradle.properties" - private const val GRADLE_PROPERTIES_LOCAL_FILE_NAME = "local.properties" - - private val gradlePropertyFiles = listOf(GRADLE_PROPERTIES_LOCAL_FILE_NAME, GRADLE_PROPERTIES_FILE_NAME) - - fun readProperty(project: Project, propertyName: String): String? { - for (propertyFileName in gradlePropertyFiles) { - val propertyFile = project.baseDir.findChild(propertyFileName) ?: continue - val properties = Properties() - properties.load(propertyFile.inputStream) - properties.getProperty(propertyName)?.let { - return it - } - } - - return null - } - - fun addCodeStyleProperty(project: Project, value: String) { - addProperty(project, KOTLIN_CODE_STYLE_GRADLE_SETTING, value) - } - - private fun addProperty(project: Project, key: String, value: String) { - val propertiesFile = projectPropertiesFile(project) - - val keyValue = "$key=$value" - - val updatedText = if (propertiesFile.exists()) { - propertiesFile.readText() + System.lineSeparator() + keyValue - } else { - keyValue - } - - propertiesFile.writeText(updatedText) - } - - private fun projectPropertiesFile(project: Project): File { - return File(getBaseDirPath(project), "gradle.properties") - } - - private fun getBaseDirPath(project: Project): File { - val basePath = project.basePath!! - return File(ExternalSystemApiUtil.toCanonicalPath(basePath)) - } -} \ No newline at end of file diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinDslGradleKotlinFrameworkSupportProvider.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinDslGradleKotlinFrameworkSupportProvider.kt index ec2fa1b9929..a595356d94d 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinDslGradleKotlinFrameworkSupportProvider.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinDslGradleKotlinFrameworkSupportProvider.kt @@ -102,7 +102,7 @@ abstract class KotlinDslGradleKotlinFrameworkSupportProvider( val isNewProject = module.project.getUserData(ExternalSystemDataKeys.NEWLY_CREATED_PROJECT) == true if (isNewProject) { ProjectCodeStyleImporter.apply(module.project, KotlinStyleGuideCodeStyle.INSTANCE) - GradlePropertiesFileUtils.addCodeStyleProperty(module.project, KotlinStyleGuideCodeStyle.CODE_STYLE_SETTING) + GradlePropertiesFileFacade.forProject(module.project).addCodeStyleProperty(KotlinStyleGuideCodeStyle.CODE_STYLE_SETTING) } } diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleAbstractMultiplatformModuleBuilder.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleAbstractMultiplatformModuleBuilder.kt index 11910a38666..a3eff296c3b 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleAbstractMultiplatformModuleBuilder.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleAbstractMultiplatformModuleBuilder.kt @@ -14,6 +14,9 @@ import com.intellij.openapi.vfs.VfsUtil import com.intellij.openapi.vfs.VirtualFile import org.jetbrains.kotlin.idea.KotlinIcons import org.jetbrains.kotlin.idea.util.rootManager +import org.jetbrains.kotlin.konan.target.HostManager +import org.jetbrains.kotlin.konan.target.KonanTarget +import org.jetbrains.kotlin.konan.target.TargetSupportException import org.jetbrains.plugins.gradle.frameworkSupport.BuildScriptDataBuilder import org.jetbrains.plugins.gradle.service.project.wizard.GradleModuleBuilder import org.jetbrains.plugins.gradle.service.settings.GradleProjectSettingsControl @@ -41,6 +44,8 @@ abstract class KotlinGradleAbstractMultiplatformModuleBuilder : GradleModuleBuil GradleKotlinMPPFrameworkSupportProvider().addSupport(builder, module, sdk = null, specifyPluginVersionIfNeeded = true) VfsUtil.saveText(buildGradle, builder.buildConfigurationPart() + builder.buildMainPart() + buildMultiPlatformPart()) createProjectSkeleton(module, rootDir) + + if (notImportedCommonSourceSets) GradlePropertiesFileFacade.forProject(module.project).addNotImportedCommonSourceSetsProperty() } finally { flushSettingsGradleCopy(module) } @@ -57,6 +62,23 @@ abstract class KotlinGradleAbstractMultiplatformModuleBuilder : GradleModuleBuil protected open fun createProjectSkeleton(module: Module, rootDir: VirtualFile) {} + protected open val notImportedCommonSourceSets = false + + protected val defaultNativeTarget by lazy { + try { + HostManager.host + } catch (e: TargetSupportException) { + KonanTarget.IOS_X64 + } + } + + // Examples: ios_x64 -> ios, macos_x64 -> macos, wasm32 -> wasm. + protected val KonanTarget.userTargetName: String + get() { + val index = name.indexOfAny("_0123456789".toCharArray()) + return if (index > 0) name.substring(0, index) else name + } + companion object { const val productionSuffix = "Main" diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleSharedMultiplatformModuleBuilder.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleSharedMultiplatformModuleBuilder.kt index 818bc5631c9..b264e69eb56 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleSharedMultiplatformModuleBuilder.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleSharedMultiplatformModuleBuilder.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.idea.configuration import com.intellij.openapi.module.Module import com.intellij.openapi.vfs.VirtualFile +import org.jetbrains.kotlin.konan.target.presetName import java.io.BufferedWriter class KotlinGradleSharedMultiplatformModuleBuilder : KotlinGradleAbstractMultiplatformModuleBuilder() { @@ -14,7 +15,7 @@ class KotlinGradleSharedMultiplatformModuleBuilder : KotlinGradleAbstractMultipl private val commonName: String = "common" private var jvmTargetName: String = "jvm" private var jsTargetName: String = "js" - private var nativeTargetName: String = "ios" + private var nativeTargetName: String = defaultNativeTarget.userTargetName private val commonSourceName get() = "$commonName$productionSuffix" private val commonTestName get() = "$commonName$testSuffix" @@ -30,7 +31,7 @@ class KotlinGradleSharedMultiplatformModuleBuilder : KotlinGradleAbstractMultipl override fun getPresentableName() = "Kotlin (Multiplatform Library)" override fun getDescription() = - "Multiplatform Gradle projects allow sharing the same Kotlin code between all three main platforms (JVM, JS, iOS)." + "Multiplatform Gradle projects allow sharing the same Kotlin code between all three main platforms (JVM, JS, Native)." override fun createProjectSkeleton(module: Module, rootDir: VirtualFile) { val src = rootDir.createChildDirectory(this, "src") @@ -42,7 +43,7 @@ class KotlinGradleSharedMultiplatformModuleBuilder : KotlinGradleAbstractMultipl val jsMain = src.createKotlinSampleFileWriter(jsSourceName) val jsTest = src.createKotlinSampleFileWriter(jsTestName, fileName = "SampleTestsJS.kt") val nativeMain = src.createKotlinSampleFileWriter(nativeSourceName) - val nativeTest = src.createKotlinSampleFileWriter(nativeTestName, fileName = "SampleTestsIOS.kt") + val nativeTest = src.createKotlinSampleFileWriter(nativeTestName, fileName = "SampleTestsNative.kt") try { commonMain.write( @@ -98,7 +99,7 @@ class KotlinGradleSharedMultiplatformModuleBuilder : KotlinGradleAbstractMultipl } actual object Platform { - actual val name: String = "iOS" + actual val name: String = "Native" } """.trimIndent() ) @@ -158,10 +159,10 @@ class KotlinGradleSharedMultiplatformModuleBuilder : KotlinGradleAbstractMultipl import kotlin.test.Test import kotlin.test.assertTrue - class SampleTestsIOS { + class SampleTestsNative { @Test fun testHello() { - assertTrue("iOS" in hello()) + assertTrue("Native" in hello()) } } """.trimIndent() @@ -180,7 +181,7 @@ class KotlinGradleSharedMultiplatformModuleBuilder : KotlinGradleAbstractMultipl // For ARM, preset should be changed to presets.iosArm32 or presets.iosArm64 // For Linux, preset should be changed to e.g. presets.linuxX64 // For MacOS, preset should be changed to e.g. presets.macosX64 - fromPreset(presets.iosX64, '$nativeTargetName') + fromPreset(presets.${defaultNativeTarget.presetName}, '${defaultNativeTarget.userTargetName}') } sourceSets { $commonSourceName { diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleSourceSetDataService.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleSourceSetDataService.kt index 2e47019f426..620893a48f0 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleSourceSetDataService.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleSourceSetDataService.kt @@ -41,9 +41,8 @@ import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor import org.jetbrains.kotlin.gradle.ArgsInfo import org.jetbrains.kotlin.gradle.CompilerArgumentsBySourceSet import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCommonCompilerArgumentsHolder +import org.jetbrains.kotlin.idea.configuration.GradlePropertiesFileFacade.Companion.KOTLIN_CODE_STYLE_GRADLE_SETTING import org.jetbrains.kotlin.idea.facet.* -import org.jetbrains.kotlin.idea.formatter.KotlinObsoleteCodeStyle -import org.jetbrains.kotlin.idea.formatter.KotlinStyleGuideCodeStyle import org.jetbrains.kotlin.idea.formatter.ProjectCodeStyleImporter import org.jetbrains.kotlin.idea.framework.CommonLibraryKind import org.jetbrains.kotlin.idea.framework.JSLibraryKind @@ -149,7 +148,7 @@ class KotlinGradleProjectDataService : AbstractProjectDataService + diff --git a/idea/src/META-INF/gradle-java.xml.as33 b/idea/src/META-INF/gradle-java.xml.as33 index fe2cf8f1268..6c64b9e1802 100644 --- a/idea/src/META-INF/gradle-java.xml.as33 +++ b/idea/src/META-INF/gradle-java.xml.as33 @@ -78,6 +78,7 @@ + diff --git a/idea/src/META-INF/gradle.xml.181 b/idea/src/META-INF/gradle.xml.181 index 895454cfc22..2a4478ee0d6 100644 --- a/idea/src/META-INF/gradle.xml.181 +++ b/idea/src/META-INF/gradle.xml.181 @@ -86,6 +86,7 @@ + diff --git a/konan/utils/src/org/jetbrains/kotlin/konan/target/KonanTarget.kt b/konan/utils/src/org/jetbrains/kotlin/konan/target/KonanTarget.kt index c37eed0b783..536726c0eb4 100644 --- a/konan/utils/src/org/jetbrains/kotlin/konan/target/KonanTarget.kt +++ b/konan/utils/src/org/jetbrains/kotlin/konan/target/KonanTarget.kt @@ -284,4 +284,16 @@ open class HostManager(subtargetProvider: SubTargetProvider = NoSubTargets()) { } } +val KonanTarget.presetName: String + get() = when (this) { + KonanTarget.ANDROID_ARM32 -> "androidNativeArm32" + KonanTarget.ANDROID_ARM64 -> "androidNativeArm64" + else -> evaluatePresetName(this.name) + } + +private fun evaluatePresetName(targetName: String): String { + val nameParts = targetName.split('_').mapNotNull { it.takeIf(String::isNotEmpty) } + return nameParts.asSequence().drop(1).joinToString("", nameParts.firstOrNull().orEmpty(), transform = String::capitalize) +} + class TargetSupportException(message: String = "", cause: Throwable? = null) : Exception(message, cause) \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt index 9368cbb63e0..cf9acf7b77f 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt @@ -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.konan.target.HostManager +import org.jetbrains.kotlin.konan.target.presetName internal val Project.multiplatformExtension get(): KotlinMultiplatformExtension? = project.extensions.getByName("kotlin") as KotlinMultiplatformExtension diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinTargetPresets.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinTargetPresets.kt index a6330711d61..c3905223263 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinTargetPresets.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinTargetPresets.kt @@ -338,13 +338,6 @@ internal val KonanTarget.isCurrentHost: Boolean internal val KonanTarget.enabledOnCurrentHost get() = HostManager().isEnabled(this) -internal val KonanTarget.presetName: String - get() = when (this) { - KonanTarget.ANDROID_ARM32 -> "androidNativeArm32" - KonanTarget.ANDROID_ARM64 -> "androidNativeArm64" - else -> lowerCamelCaseName(*this.name.split('_').toTypedArray()) - } - internal val KotlinNativeCompilation.isMainCompilation: Boolean get() = name == KotlinCompilation.MAIN_COMPILATION_NAME