From 721aa81ca55d8373eba95cc08d201eaaea8efd7a Mon Sep 17 00:00:00 2001 From: Anton Yalyshev Date: Tue, 24 Sep 2019 17:29:24 +0300 Subject: [PATCH] Relying on platform stepping goes better only from 2019.3 --- ...radleAbstractMultiplatformModuleBuilder.kt | 13 + ...eAbstractMultiplatformModuleBuilder.kt.193 | 188 ++++++++++++++ ...eMobileSharedMultiplatformModuleBuilder.kt | 4 +- ...ileSharedMultiplatformModuleBuilder.kt.193 | 205 +++++++++++++++ ...nGradleSharedMultiplatformModuleBuilder.kt | 4 +- ...dleSharedMultiplatformModuleBuilder.kt.193 | 237 ++++++++++++++++++ 6 files changed, 647 insertions(+), 4 deletions(-) create mode 100644 idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleAbstractMultiplatformModuleBuilder.kt.193 create mode 100644 idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleMobileSharedMultiplatformModuleBuilder.kt.193 create mode 100644 idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleSharedMultiplatformModuleBuilder.kt.193 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 1ce22284b6c..28f9591bf69 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 @@ -5,11 +5,15 @@ package org.jetbrains.kotlin.idea.configuration +import com.intellij.ide.util.projectWizard.ModuleWizardStep +import com.intellij.ide.util.projectWizard.WizardContext import com.intellij.openapi.externalSystem.ExternalSystemModulePropertyManager import com.intellij.openapi.externalSystem.model.ProjectSystemId import com.intellij.openapi.externalSystem.model.project.ModuleData +import com.intellij.openapi.externalSystem.service.project.wizard.ExternalModuleSettingsStep import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil import com.intellij.openapi.module.Module +import com.intellij.openapi.roots.ui.configuration.ModulesProvider import com.intellij.openapi.vfs.VfsUtil import com.intellij.openapi.vfs.VirtualFile import org.jetbrains.kotlin.idea.KotlinIcons @@ -19,6 +23,7 @@ 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 import org.jetbrains.plugins.gradle.settings.DistributionType import com.intellij.openapi.externalSystem.model.project.ProjectData import org.jetbrains.kotlin.idea.statistics.FUSEventGroups @@ -33,6 +38,14 @@ abstract class KotlinGradleAbstractMultiplatformModuleBuilder( override fun getNodeIcon(): Icon = KotlinIcons.MPP + override fun createWizardSteps(wizardContext: WizardContext, modulesProvider: ModulesProvider): Array { + super.createWizardSteps(wizardContext, modulesProvider) // initializes GradleModuleBuilder.myWizardContext + return arrayOf( + // Let us have to edit project name only + ExternalModuleSettingsStep(wizardContext, this, GradleProjectSettingsControl(externalProjectSettings)) + ) + } + private fun setupMppModule(module: Module, parentDir: VirtualFile): VirtualFile? { val moduleDir = parentDir.createChildDirectory(this, mppDirName) val buildGradle = moduleDir.createChildData(null, "build.gradle") diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleAbstractMultiplatformModuleBuilder.kt.193 b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleAbstractMultiplatformModuleBuilder.kt.193 new file mode 100644 index 00000000000..1ce22284b6c --- /dev/null +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleAbstractMultiplatformModuleBuilder.kt.193 @@ -0,0 +1,188 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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.ExternalSystemModulePropertyManager +import com.intellij.openapi.externalSystem.model.ProjectSystemId +import com.intellij.openapi.externalSystem.model.project.ModuleData +import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil +import com.intellij.openapi.module.Module +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.settings.DistributionType +import com.intellij.openapi.externalSystem.model.project.ProjectData +import org.jetbrains.kotlin.idea.statistics.FUSEventGroups +import org.jetbrains.kotlin.idea.statistics.KotlinFUSLogger +import javax.swing.Icon + +abstract class KotlinGradleAbstractMultiplatformModuleBuilder( + val mppInApplication: Boolean = false +) : GradleModuleBuilder() { + var explicitPluginVersion: String? = null + val mppDirName = "app" + + override fun getNodeIcon(): Icon = KotlinIcons.MPP + + private fun setupMppModule(module: Module, parentDir: VirtualFile): VirtualFile? { + val moduleDir = parentDir.createChildDirectory(this, mppDirName) + val buildGradle = moduleDir.createChildData(null, "build.gradle") + val builder = BuildScriptDataBuilder(buildGradle) + builder.setupAdditionalDependenciesForApplication() + GradleKotlinMPPFrameworkSupportProvider().addSupport( + builder, + module, + sdk = null, + specifyPluginVersionIfNeeded = true, + explicitPluginVersion = explicitPluginVersion + ) + VfsUtil.saveText(buildGradle, builder.buildConfigurationPart() + builder.buildMainPart() + buildMultiPlatformPart()) + return moduleDir + } + + private fun enableGradleMetadataPreview(rootDir: VirtualFile) { + val settingsGradle = rootDir.findOrCreateChildData(null, "settings.gradle") + val previousText = settingsGradle.inputStream.bufferedReader().use { it.readText() } + settingsGradle.bufferedWriter().use { + it.write(previousText) + if (previousText.isNotEmpty()) { + it.newLine() + } + it.write("enableFeaturePreview('GRADLE_METADATA')") + it.newLine() + } + } + + override fun setupModule(module: Module) { + try { + KotlinFUSLogger.log(FUSEventGroups.NPWizards, this.javaClass.simpleName) + module.gradleModuleBuilder = this + super.setupModule(module) + + val rootDir = module.rootManager.contentRoots.firstOrNull() ?: return + val buildGradle = rootDir.findOrCreateChildData(null, "build.gradle") + if (mppInApplication) { + setupMppModule(module, rootDir) + } + val builder = BuildScriptDataBuilder(buildGradle) + builder.setupAdditionalDependencies() + if (shouldEnableGradleMetadataPreview) { + enableGradleMetadataPreview(rootDir) + } + val buildGradleText = if (!mppInApplication) { + GradleKotlinMPPFrameworkSupportProvider().addSupport( + builder, + module, + sdk = null, + specifyPluginVersionIfNeeded = true, + explicitPluginVersion = explicitPluginVersion + ) + builder.buildConfigurationPart() + builder.buildMainPart() + buildMultiPlatformPart() + } else { + builder.buildConfigurationPart() + builder.buildMainPart() + } + VfsUtil.saveText(buildGradle, buildGradleText) + if (mppInApplication) { + updateSettingsScript(module) { + it.addIncludedModules(listOf(":$mppDirName")) + } + } + createProjectSkeleton(rootDir) + if (externalProjectSettings.distributionType == DistributionType.DEFAULT_WRAPPED) { + setGradleWrapperToUseVersion(rootDir, "4.10") + } + + if (notImportedCommonSourceSets) GradlePropertiesFileFacade.forProject(module.project).addNotImportedCommonSourceSetsProperty() + // Ensure project root path is set + val propertyManager = ExternalSystemModulePropertyManager.getInstance(module) + val path = externalProjectSettings.externalProjectPath + val externalSystemId = propertyManager.getExternalSystemId() + if (ExternalSystemApiUtil.getExternalRootProjectPath(module) == null && externalSystemId != null) { + val projectSystemId = ProjectSystemId(externalSystemId) + val projectData = ProjectData(projectSystemId, module.name, path, path) + val moduleData = ModuleData( + propertyManager.getLinkedProjectId() ?: "", + projectSystemId, + propertyManager.getExternalModuleType() ?: "", + module.name, + path, + path + ) + propertyManager.setExternalOptions(projectSystemId, moduleData, projectData) + } + } finally { + flushSettingsGradleCopy(module) + } + } + + private fun setGradleWrapperToUseVersion(rootDir: VirtualFile, version: String) { + val wrapperDir = rootDir.createChildDirectory(null, "gradle").createChildDirectory(null, "wrapper") + val wrapperProperties = wrapperDir.createChildData(null, "gradle-wrapper.properties").bufferedWriter() + wrapperProperties.use { + it.write( + """ + distributionBase=GRADLE_USER_HOME + distributionPath=wrapper/dists + distributionUrl=https\://services.gradle.org/distributions/gradle-$version-bin.zip + zipStoreBase=GRADLE_USER_HOME + zipStorePath=wrapper/dists + """.trimIndent() + ) + } + } + + protected abstract fun buildMultiPlatformPart(): String + + protected open fun BuildScriptDataBuilder.setupAdditionalDependencies() {} + + protected open fun BuildScriptDataBuilder.setupAdditionalDependenciesForApplication() {} + + protected fun VirtualFile.bufferedWriter() = getOutputStream(this).bufferedWriter() + + protected fun VirtualFile.createKotlinSampleFileWriter( + sourceRootName: String, + platformName: String = "", + languageName: String = "kotlin", + fileName: String = "Sample${platformName.capitalize()}.kt" + ) = createChildDirectory(this, sourceRootName) + .createChildDirectory(this, languageName) + .createChildDirectory(this, "sample") + .createChildData(this, fileName) + .bufferedWriter() + + protected open fun createProjectSkeleton(rootDir: VirtualFile) {} + + protected open val notImportedCommonSourceSets = false + + protected open val shouldEnableGradleMetadataPreview = 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" + + const val testSuffix = "Test" + } +} \ No newline at end of file diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleMobileSharedMultiplatformModuleBuilder.kt b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleMobileSharedMultiplatformModuleBuilder.kt index 83c78568311..5136c8c33ea 100644 --- a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleMobileSharedMultiplatformModuleBuilder.kt +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleMobileSharedMultiplatformModuleBuilder.kt @@ -139,8 +139,8 @@ class KotlinGradleMobileSharedMultiplatformModuleBuilder : KotlinGradleAbstractM override fun buildMultiPlatformPart(): String { return """ - group '${projectId.groupId ?: "com.example"}' - version '${projectId.version ?: "0.0.1"}' + group 'com.example' + version '0.0.1' apply plugin: 'maven-publish' diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleMobileSharedMultiplatformModuleBuilder.kt.193 b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleMobileSharedMultiplatformModuleBuilder.kt.193 new file mode 100644 index 00000000000..83c78568311 --- /dev/null +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleMobileSharedMultiplatformModuleBuilder.kt.193 @@ -0,0 +1,205 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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.vfs.VirtualFile +import java.io.BufferedWriter + +class KotlinGradleMobileSharedMultiplatformModuleBuilder : KotlinGradleAbstractMultiplatformModuleBuilder() { + + private val commonName: String = "common" + private var jvmTargetName: String = "jvm" + private var nativeTargetName: String = "ios" + + private val commonSourceName get() = "$commonName$productionSuffix" + private val commonTestName get() = "$commonName$testSuffix" + private val jvmSourceName get() = "$jvmTargetName$productionSuffix" + private val jvmTestName get() = "$jvmTargetName$testSuffix" + private val nativeSourceName get() = "$nativeTargetName$productionSuffix" + val nativeTestName get() = "$nativeTargetName$testSuffix" + + override val shouldEnableGradleMetadataPreview: Boolean = true + + override fun getBuilderId() = "kotlin.gradle.multiplatform.mobileshared" + + override fun getPresentableName() = "Mobile Shared Library | Gradle" + + override fun getDescription() = + "Multiplatform Gradle project allowing reuse of the same Kotlin code between two mobile platforms (JVM/Android and Native)" + + override fun createProjectSkeleton(rootDir: VirtualFile) { + val src = rootDir.createChildDirectory(this, "src") + + val commonMain = src.createKotlinSampleFileWriter(commonSourceName) + val commonTest = src.createKotlinSampleFileWriter(commonTestName, fileName = "SampleTests.kt") + val jvmMain = src.createKotlinSampleFileWriter(jvmSourceName, jvmTargetName) + val jvmTest = src.createKotlinSampleFileWriter(jvmTestName, fileName = "SampleTestsJVM.kt") + val nativeMain = src.createKotlinSampleFileWriter(nativeSourceName, nativeTargetName) + val nativeTest = src.createKotlinSampleFileWriter(nativeTestName, fileName = "SampleTestsNative.kt") + + try { + commonMain.write( + """ + package sample + + expect class Sample() { + fun checkMe(): Int + } + + expect object Platform { + fun name(): String + } + + fun hello(): String = "Hello from ${"$"}{Platform.name()}" + """.trimIndent() + ) + + jvmMain.write( + """ + package sample + + actual class Sample { + actual fun checkMe() = 42 + } + + actual object Platform { + actual fun name(): String = "JVM" + } + """.trimIndent() + ) + + nativeMain.write( + """ + package sample + + actual class Sample { + actual fun checkMe() = 7 + } + + actual object Platform { + actual fun name(): String = "iOS" + } + """.trimIndent() + ) + + commonTest.write( + """ + package sample + + import kotlin.test.Test + import kotlin.test.assertTrue + + class SampleTests { + @Test + fun testMe() { + assertTrue(Sample().checkMe() > 0) + } + } + """.trimIndent() + ) + + jvmTest.write( + """ + package sample + + import kotlin.test.Test + import kotlin.test.assertTrue + + class SampleTestsJVM { + @Test + fun testHello() { + assertTrue("JVM" in hello()) + } + } + """.trimIndent() + ) + + nativeTest.write( + """ + package sample + + import kotlin.test.Test + import kotlin.test.assertTrue + + class SampleTestsNative { + @Test + fun testHello() { + assertTrue("iOS" in hello()) + } + } + """.trimIndent() + ) + } finally { + listOf(commonMain, commonTest, jvmMain, jvmTest, nativeMain, nativeTest).forEach(BufferedWriter::close) + } + } + + override fun buildMultiPlatformPart(): String { + return """ + group '${projectId.groupId ?: "com.example"}' + version '${projectId.version ?: "0.0.1"}' + + apply plugin: 'maven-publish' + + kotlin { + jvm() + // This is for iPhone emulator + // Switch here to iosArm64 (or iosArm32) to build library for iPhone device + iosX64("$nativeTargetName") { + binaries { + framework() + } + } + sourceSets { + $commonSourceName { + dependencies { + implementation kotlin('stdlib-common') + } + } + $commonTestName { + dependencies { + implementation kotlin('test-common') + implementation kotlin('test-annotations-common') + } + } + $jvmSourceName { + dependencies { + implementation kotlin('stdlib') + } + } + $jvmTestName { + dependencies { + implementation kotlin('test') + implementation kotlin('test-junit') + } + } + $nativeSourceName { + } + $nativeTestName { + } + } + } + + task $nativeTestName { + def device = project.findProperty("${nativeTargetName}Device")?.toString() ?: "iPhone 8" + dependsOn kotlin.targets.$nativeTargetName.binaries.getTest('DEBUG').linkTaskName + group = JavaBasePlugin.VERIFICATION_GROUP + description = "Runs tests for target '$nativeTargetName' on an iOS simulator" + + doLast { + def binary = kotlin.targets.$nativeTargetName.binaries.getTest('DEBUG').outputFile + exec { + commandLine 'xcrun', 'simctl', 'spawn', device, binary.absolutePath + } + } + } + + configurations { + compileClasspath + } + """.trimIndent() + } +} \ No newline at end of file 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 525402f3ee7..068b21f7d66 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 @@ -175,8 +175,8 @@ class KotlinGradleSharedMultiplatformModuleBuilder : KotlinGradleAbstractMultipl override fun buildMultiPlatformPart(): String { return """ - group '${projectId.groupId ?: "com.example"}' - version '${projectId.version ?: "0.0.1"}' + group 'com.example' + version '0.0.1' apply plugin: 'maven-publish' diff --git a/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleSharedMultiplatformModuleBuilder.kt.193 b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleSharedMultiplatformModuleBuilder.kt.193 new file mode 100644 index 00000000000..525402f3ee7 --- /dev/null +++ b/idea/idea-gradle/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleSharedMultiplatformModuleBuilder.kt.193 @@ -0,0 +1,237 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. + * 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.vfs.VirtualFile +import org.jetbrains.kotlin.konan.target.presetName +import java.io.BufferedWriter + +class KotlinGradleSharedMultiplatformModuleBuilder : KotlinGradleAbstractMultiplatformModuleBuilder() { + + private val commonName: String = "common" + private var jvmTargetName: String = "jvm" + private var jsTargetName: String = "js" + private var nativeTargetName: String = defaultNativeTarget.userTargetName + + private val commonSourceName get() = "$commonName$productionSuffix" + private val commonTestName get() = "$commonName$testSuffix" + private val jvmSourceName get() = "$jvmTargetName$productionSuffix" + private val jvmTestName get() = "$jvmTargetName$testSuffix" + private val jsSourceName get() = "$jsTargetName$productionSuffix" + private val jsTestName get() = "$jsTargetName$testSuffix" + private val nativeSourceName get() = "$nativeTargetName$productionSuffix" + val nativeTestName get() = "$nativeTargetName$testSuffix" + + override val shouldEnableGradleMetadataPreview: Boolean = true + + override fun getBuilderId() = "kotlin.gradle.multiplatform.shared" + + override fun getPresentableName() = "Multiplatform Library | Gradle" + + override fun getDescription() = + "Multiplatform Gradle project allowing reuse of the same Kotlin code between all three main platforms (JVM, JS, and Native)" + + override fun createProjectSkeleton(rootDir: VirtualFile) { + val src = rootDir.createChildDirectory(this, "src") + + val commonMain = src.createKotlinSampleFileWriter(commonSourceName) + val commonTest = src.createKotlinSampleFileWriter(commonTestName, fileName = "SampleTests.kt") + val jvmMain = src.createKotlinSampleFileWriter(jvmSourceName, jvmTargetName) + val jvmTest = src.createKotlinSampleFileWriter(jvmTestName, fileName = "SampleTestsJVM.kt") + val jsMain = src.createKotlinSampleFileWriter(jsSourceName, jsTargetName) + val jsTest = src.createKotlinSampleFileWriter(jsTestName, fileName = "SampleTestsJS.kt") + val nativeMain = src.createKotlinSampleFileWriter(nativeSourceName, nativeTargetName) + val nativeTest = src.createKotlinSampleFileWriter(nativeTestName, fileName = "SampleTestsNative.kt") + + try { + commonMain.write( + """ + package sample + + expect class Sample() { + fun checkMe(): Int + } + + expect object Platform { + val name: String + } + + fun hello(): String = "Hello from ${"$"}{Platform.name}" + """.trimIndent() + ) + + jvmMain.write( + """ + package sample + + actual class Sample { + actual fun checkMe() = 42 + } + + actual object Platform { + actual val name: String = "JVM" + } + """.trimIndent() + ) + + jsMain.write( + """ + package sample + + actual class Sample { + actual fun checkMe() = 12 + } + + actual object Platform { + actual val name: String = "JS" + } + """.trimIndent() + ) + + nativeMain.write( + """ + package sample + + actual class Sample { + actual fun checkMe() = 7 + } + + actual object Platform { + actual val name: String = "Native" + } + """.trimIndent() + ) + + commonTest.write( + """ + package sample + + import kotlin.test.Test + import kotlin.test.assertTrue + + class SampleTests { + @Test + fun testMe() { + assertTrue(Sample().checkMe() > 0) + } + } + """.trimIndent() + ) + + jvmTest.write( + """ + package sample + + import kotlin.test.Test + import kotlin.test.assertTrue + + class SampleTestsJVM { + @Test + fun testHello() { + assertTrue("JVM" in hello()) + } + } + """.trimIndent() + ) + + jsTest.write( + """ + package sample + + import kotlin.test.Test + import kotlin.test.assertTrue + + class SampleTestsJS { + @Test + fun testHello() { + assertTrue("JS" in hello()) + } + } + """.trimIndent() + ) + + nativeTest.write( + """ + package sample + + import kotlin.test.Test + import kotlin.test.assertTrue + + class SampleTestsNative { + @Test + fun testHello() { + assertTrue("Native" in hello()) + } + } + """.trimIndent() + ) + } finally { + listOf(commonMain, commonTest, jvmMain, jvmTest, jsMain, jsTest, nativeMain, nativeTest).forEach(BufferedWriter::close) + } + } + + override fun buildMultiPlatformPart(): String { + return """ + group '${projectId.groupId ?: "com.example"}' + version '${projectId.version ?: "0.0.1"}' + + apply plugin: 'maven-publish' + + kotlin { + jvm() + js { + browser { + } + nodejs { + } + } + // For ARM, should be changed to iosArm32 or iosArm64 + // For Linux, should be changed to e.g. linuxX64 + // For MacOS, should be changed to e.g. macosX64 + // For Windows, should be changed to e.g. mingwX64 + ${defaultNativeTarget.presetName}("${defaultNativeTarget.userTargetName}") + sourceSets { + $commonSourceName { + dependencies { + implementation kotlin('stdlib-common') + } + } + $commonTestName { + dependencies { + implementation kotlin('test-common') + implementation kotlin('test-annotations-common') + } + } + $jvmSourceName { + dependencies { + implementation kotlin('stdlib-jdk8') + } + } + $jvmTestName { + dependencies { + implementation kotlin('test') + implementation kotlin('test-junit') + } + } + $jsSourceName { + dependencies { + implementation kotlin('stdlib-js') + } + } + $jsTestName { + dependencies { + implementation kotlin('test-js') + } + } + $nativeSourceName { + } + $nativeTestName { + } + } + } + """.trimIndent() + } +} \ No newline at end of file