From 2441df820b632066e89873e8605c824cdac98e21 Mon Sep 17 00:00:00 2001 From: Sergey Igushkin Date: Thu, 27 Sep 2018 00:39:04 +0300 Subject: [PATCH] Support Kotlin/JS DCE in new MPP Issue #KT-27196 Fixed --- .../kotlin/gradle/NewMultiplatformIT.kt | 16 +++++++ .../libraryProject/build.gradle | 33 +++++++++++++ .../src/nodeJsMain/kotlin/examplelib/lib.kt | 6 +++ .../new-mpp-js-dce/mainProject/build.gradle | 44 ++++++++++++++++++ .../new-mpp-js-dce/mainProject/check.js | 6 +++ .../src/nodeJsMain/kotlin/exampleapp/main.kt | 9 ++++ .../new-mpp-js-dce/settings.gradle | 1 + .../kotlin/gradle/plugin/KotlinJsDcePlugin.kt | 46 +++++++++++++++---- .../plugin/mpp/KotlinMultiplatformPlugin.kt | 2 +- 9 files changed, 152 insertions(+), 11 deletions(-) create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-js-dce/libraryProject/build.gradle create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-js-dce/libraryProject/src/nodeJsMain/kotlin/examplelib/lib.kt create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-js-dce/mainProject/build.gradle create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-js-dce/mainProject/check.js create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-js-dce/mainProject/src/nodeJsMain/kotlin/exampleapp/main.kt create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-js-dce/settings.gradle diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NewMultiplatformIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NewMultiplatformIT.kt index d9dd63fe844..3c0980866bc 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NewMultiplatformIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NewMultiplatformIT.kt @@ -846,4 +846,20 @@ class NewMultiplatformIT : BaseGradleIT() { } } } + + @Test + fun testJsDceInMpp() = with(Project("new-mpp-js-dce", gradleVersion)) { + build("runRhino") { + assertSuccessful() + assertTasksExecuted(":mainProject:runDceNodeJsKotlin") + + val pathPrefix = "mainProject/build/kotlin-js-min/nodeJs/main" + assertFileExists("$pathPrefix/exampleapp.js.map") + assertFileExists("$pathPrefix/examplelib.js.map") + assertFileContains("$pathPrefix/exampleapp.js.map", "\"../../../../src/nodeJsMain/kotlin/exampleapp/main.kt\"") + + assertFileExists("$pathPrefix/kotlin.js") + assertTrue(fileInWorkingDir("$pathPrefix/kotlin.js").length() < 500 * 1000, "Looks like kotlin.js file was not minified by DCE") + } + } } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-js-dce/libraryProject/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-js-dce/libraryProject/build.gradle new file mode 100644 index 00000000000..6ed6da6ab89 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-js-dce/libraryProject/build.gradle @@ -0,0 +1,33 @@ +buildscript { + repositories { + mavenLocal() + mavenCentral() + } + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +apply plugin: 'kotlin-multiplatform' + +repositories { + mavenLocal() + mavenCentral() +} + +kotlin.targets.fromPreset(kotlin.presets.js, 'nodeJs') + +dependencies { + nodeJsMainApi "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlin_version" +} + +compileKotlinNodeJs.kotlinOptions.outputFile = "${buildDir}/examplelib.js" +compileKotlinNodeJs.kotlinOptions.sourceMap = true + +nodeJsJar { + from buildDir + include "**/*.js" + include "**/*.js.map" +} + +nodeJsJar.dependsOn(compileKotlinNodeJs) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-js-dce/libraryProject/src/nodeJsMain/kotlin/examplelib/lib.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-js-dce/libraryProject/src/nodeJsMain/kotlin/examplelib/lib.kt new file mode 100644 index 00000000000..70f59d4e7bc --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-js-dce/libraryProject/src/nodeJsMain/kotlin/examplelib/lib.kt @@ -0,0 +1,6 @@ +package examplelib + +fun foo() = "foo" + +fun bar() = "bar" + diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-js-dce/mainProject/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-js-dce/mainProject/build.gradle new file mode 100644 index 00000000000..d3a619fb31b --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-js-dce/mainProject/build.gradle @@ -0,0 +1,44 @@ +buildscript { + repositories { + mavenLocal() + mavenCentral() + } + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +apply plugin: "kotlin-multiplatform" +apply plugin: "kotlin-dce-js" + +repositories { + mavenLocal() + mavenCentral() +} + +kotlin.targets.fromPreset(kotlin.presets.js, 'nodeJs') + +dependencies { + nodeJsImplementation project(":libraryProject") + nodeJsImplementation "org.jetbrains.kotlin:kotlin-stdlib-js" + nodeJsImplementation "org.mozilla:rhino:1.7.7.1" +} + +compileKotlinNodeJs.kotlinOptions.sourceMap = true +compileKotlinNodeJs.kotlinOptions.outputFile = "${buildDir}/exampleapp.js" +compileKotlinNodeJs.kotlinOptions.suppressWarnings = true +compileKotlinNodeJs.kotlinOptions.verbose = true +runDceNodeJsKotlin.keep("exampleapp.exampleapp.status") + +task runRhino(type: JavaExec) { + classpath = kotlin.targets.nodeJs.compilations.main.runtimeDependencyFiles + workingDir = "${buildDir}" + main = 'org.mozilla.javascript.tools.shell.Main' + args = ["-opt", "-1", + "-f", "kotlin-js-min/nodeJs/main/kotlin.js", + "-f", "kotlin-js-min/nodeJs/main/examplelib.js", + "-f", "kotlin-js-min/nodeJs/main/exampleapp.js", + "-f", "../check.js"] +} + +runRhino.dependsOn(runDceNodeJsKotlin) \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-js-dce/mainProject/check.js b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-js-dce/mainProject/check.js new file mode 100644 index 00000000000..213b8394c17 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-js-dce/mainProject/check.js @@ -0,0 +1,6 @@ +(function() { + var status = exampleapp.exampleapp.status; + if (status !== "foo") { + throw new Error("Unexpected status: " + status); + } +})(); diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-js-dce/mainProject/src/nodeJsMain/kotlin/exampleapp/main.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-js-dce/mainProject/src/nodeJsMain/kotlin/exampleapp/main.kt new file mode 100644 index 00000000000..6c9550597d2 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-js-dce/mainProject/src/nodeJsMain/kotlin/exampleapp/main.kt @@ -0,0 +1,9 @@ +package exampleapp + +import examplelib.* + +var status = "failure" + +fun main(args: Array) { + status = foo() +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-js-dce/settings.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-js-dce/settings.gradle new file mode 100644 index 00000000000..9eeb29d9776 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-js-dce/settings.gradle @@ -0,0 +1 @@ +include 'mainProject', 'libraryProject' \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinJsDcePlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinJsDcePlugin.kt index c223f9da342..4ae6799d045 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinJsDcePlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinJsDcePlugin.kt @@ -18,33 +18,58 @@ package org.jetbrains.kotlin.gradle.plugin import org.gradle.api.Plugin import org.gradle.api.Project -import org.gradle.api.plugins.JavaPluginConvention -import org.gradle.api.tasks.SourceSet +import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension +import org.jetbrains.kotlin.gradle.dsl.KotlinSingleJavaTargetExtension +import org.jetbrains.kotlin.gradle.dsl.kotlinExtension +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinWithJavaTarget +import org.jetbrains.kotlin.gradle.plugin.mpp.multiplatformExtension import org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile import org.jetbrains.kotlin.gradle.tasks.KotlinJsDce +import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName import java.io.File class KotlinJsDcePlugin : Plugin { override fun apply(project: Project) { - project.pluginManager.apply(Kotlin2JsPluginWrapper::class.java) + val kotlinExtension = project.multiplatformExtension ?: run { + project.pluginManager.apply(Kotlin2JsPluginWrapper::class.java) + project.kotlinExtension as KotlinSingleJavaTargetExtension + } - val javaPluginConvention = project.convention.getPlugin(JavaPluginConvention::class.java) - javaPluginConvention.sourceSets.forEach { processSourceSet(project, it) } + fun forEachJsTarget(action: (KotlinTarget) -> Unit) { + when (kotlinExtension) { + is KotlinSingleJavaTargetExtension -> action(kotlinExtension.target) + is KotlinMultiplatformExtension -> + kotlinExtension.targets + .matching { it.platformType == KotlinPlatformType.js } + .all { action(it) } + } + } + + forEachJsTarget { + it.compilations.all { processCompilation(project, it) } + } } - private fun processSourceSet(project: Project, sourceSet: SourceSet) { - val kotlinTaskName = sourceSet.getCompileTaskName("kotlin2Js") + private fun processCompilation(project: Project, kotlinCompilation: KotlinCompilation) { + val kotlinTaskName = kotlinCompilation.compileKotlinTaskName val kotlinTask = project.tasks.findByName(kotlinTaskName) as? Kotlin2JsCompile ?: return - val dceTaskName = sourceSet.getTaskName(DCE_TASK_PREFIX, TASK_SUFFIX) + val dceTaskName = lowerCamelCaseName( + DCE_TASK_PREFIX, + kotlinCompilation.target.disambiguationClassifier, + kotlinCompilation.name.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME }, + if (kotlinCompilation.target is KotlinWithJavaTarget) TASK_SUFFIX else MPP_TASK_SUFFIX + ) val dceTask = project.tasks.create(dceTaskName, KotlinJsDce::class.java).also { it.dependsOn(kotlinTask) project.tasks.findByName("build")!!.dependsOn(it) } project.afterEvaluate { - val outputDir = File(File(project.buildDir, DEFAULT_OUT_DIR), sourceSet.name) + val outputDir = project.buildDir + .resolve(DEFAULT_OUT_DIR) + .resolve(kotlinCompilation.target.disambiguationClassifier?.let { "$it/" }.orEmpty() + kotlinCompilation.name) - val configuration = project.configurations.findByName(sourceSet.compileConfigurationName)!! + val configuration = project.configurations.getByName(kotlinCompilation.compileDependencyConfigurationName) with (dceTask) { classpath = configuration @@ -56,6 +81,7 @@ class KotlinJsDcePlugin : Plugin { companion object { private const val TASK_SUFFIX = "kotlinJs" + private const val MPP_TASK_SUFFIX = "kotlin" private const val DCE_TASK_PREFIX = "runDce" private const val DEFAULT_OUT_DIR = "kotlin-js-min" } 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 607513e0282..30ca580baee 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 @@ -31,7 +31,7 @@ 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 + project.extensions.findByName("kotlin") as? KotlinMultiplatformExtension class KotlinMultiplatformPlugin( private val buildOutputCleanupRegistry: BuildOutputCleanupRegistry,