diff --git a/libraries/tools/kotlin-gradle-plugin-annotations/src/main/kotlin/org/jetbrains/kotlin/gradle/ExperimentalWasmDsl.kt b/libraries/tools/kotlin-gradle-plugin-annotations/src/main/kotlin/org/jetbrains/kotlin/gradle/ExperimentalWasmDsl.kt index ac06117c3fc59..72ee343c0e880 100644 --- a/libraries/tools/kotlin-gradle-plugin-annotations/src/main/kotlin/org/jetbrains/kotlin/gradle/ExperimentalWasmDsl.kt +++ b/libraries/tools/kotlin-gradle-plugin-annotations/src/main/kotlin/org/jetbrains/kotlin/gradle/ExperimentalWasmDsl.kt @@ -6,5 +6,5 @@ package org.jetbrains.kotlin.gradle @RequiresOptIn(level = RequiresOptIn.Level.WARNING) -@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY) +@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY) annotation class ExperimentalWasmDsl \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NodeJsGradlePluginIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NodeJsGradlePluginIT.kt new file mode 100644 index 0000000000000..1c93434d4df80 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NodeJsGradlePluginIT.kt @@ -0,0 +1,88 @@ +/* + * Copyright 2010-2020 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.gradle + +import org.gradle.api.Action +import org.gradle.util.GradleVersion +import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension +import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin +import org.jetbrains.kotlin.gradle.testbase.* +import org.jetbrains.kotlin.test.TestMetadata +import org.junit.jupiter.api.DisplayName + + +@MppGradlePluginTests +class NodeJsGradlePluginIT : KGPBaseTest() { + @DisplayName("Set different Node.js versions in different subprojects") + @GradleTest + @TestMetadata("subprojects-nodejs-setup") + fun testDifferentVersionInSubprojects(gradleVersion: GradleVersion) { + project( + "subprojects-nodejs-setup", + gradleVersion + ) { + build(":app1:jsNodeDevelopmentRun") { + assertOutputContains("Hello with version: v22.2.0") + } + + build(":app2:jsNodeDevelopmentRun") { + assertOutputContains("Hello with version: v22.1.0") + } + } + } + + @DisplayName("Set different Node.js versions in different subprojects configured with previous API") + @GradleTest + @TestMetadata("subprojects-nodejs-setup") + fun testDifferentVersionInSubprojectsWithPreviousApi(gradleVersion: GradleVersion) { + project( + "subprojects-nodejs-setup", + gradleVersion + ) { + listOf("app1", "app2").forEach { subProjectName -> + subProject(subProjectName).buildGradleKts.modify { + it.replace("plugins.", "rootProject.plugins.") + .replace("the", "rootProject.the") + .replace("NodeJsPlugin", "NodeJsRootPlugin") + .replace("NodeJsEnvSpec", "NodeJsRootExtension") + .replace("""version\.set\(("\d+\.\d+.\d+")\)""".toRegex(), "version = \"22.3.0\"") + } + } + + build(":app1:jsNodeDevelopmentRun") { + assertOutputContains("Hello with version: v22.3.0") + } + + build(":app2:jsNodeDevelopmentRun") { + assertOutputContains("Hello with version: v22.3.0") + } + } + } + + @DisplayName("Set different Node.js versions in root project and subprojects") + @GradleTest + @TestMetadata("subprojects-nodejs-setup") + fun testDifferentVersionInRootProjectAndSubprojects(gradleVersion: GradleVersion) { + project( + "subprojects-nodejs-setup", + gradleVersion + ) { + buildScriptInjection { + project.rootProject.plugins.withType(NodeJsRootPlugin::class.java, Action { + project.rootProject.extensions.getByType(NodeJsRootExtension::class.java).version = "22.3.0" + }) + } + + build(":app1:jsNodeDevelopmentRun") { + assertOutputContains("Hello with version: v22.2.0") + } + + build(":app2:jsNodeDevelopmentRun") { + assertOutputContains("Hello with version: v22.1.0") + } + } + } +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-js-browser-project/app/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-js-browser-project/app/build.gradle.kts index 80f49d1341f19..5245de12205f9 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-js-browser-project/app/build.gradle.kts +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-js-browser-project/app/build.gradle.kts @@ -1,6 +1,4 @@ -import org.jetbrains.kotlin.gradle.targets.js.NpmVersions -import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrLink -import javax.inject.Inject +import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject plugins { kotlin("js") @@ -56,20 +54,25 @@ kotlin { customField("customField5", "@as/${nameOfModule}") } } - } -} - -rootProject.plugins.withType { - val kotlinNodeJs = rootProject.extensions.getByType() - tasks.register("runWebpackResult") { - val webpackTask = tasks.named("browserProductionWebpack") - dependsOn(webpackTask) + val mainCompilation = compilations["main"] + rootProject.plugins.withType { + tasks.register("runWebpackResult") { + val webpackTask = tasks.named("browserProductionWebpack") + dependsOn(webpackTask) - executable(kotlinNodeJs.requireConfigured().nodeExecutable) + val workDir = webpackTask.flatMap { it.outputDirectory.asFile } - workingDir(webpackTask.flatMap { it.outputDirectory.asFile }) - args("./${project.name}.js") + val npmProject = mainCompilation.npmProject + val projectName = project.name + doFirst { + this as Exec + npmProject.useTool(this, "webpack/bin/webpack", args = listOf()) + this.args = listOf("./$projectName.js") + workingDir(workDir) + } + } + } } } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-js-dce/mainProject/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-js-dce/mainProject/build.gradle index db51fbabb38f5..1ef1bc76bb5f4 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-js-dce/mainProject/build.gradle +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kotlin-js-dce/mainProject/build.gradle @@ -1,3 +1,5 @@ +import org.jetbrains.kotlin.gradle.targets.js.npm.NpmProjectKt + plugins { id("org.jetbrains.kotlin.js") } @@ -16,6 +18,28 @@ kotlin { js { binaries.executable() browser() + + rootProject.plugins.withType(org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin) { +// def kotlinNodeJs = rootProject.extensions.getByType(org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsExtension) + + def mainCompilation = compilations["main"] + + tasks.register("runWebpack", Exec) { + dependsOn(tasks.named('browserProductionWebpack')) + + workingDir = "${rootProject.buildDir}/js/packages/kotlin-js-dce-mainProject" + + def npmProject = NpmProjectKt.getNpmProject(mainCompilation) + + doFirst { + npmProject.useTool(it, "webpack/bin/webpack", [], []) + } + } + + tasks.named("assemble") { + dependsOn("runWebpack") + } + } } } @@ -33,23 +57,6 @@ kotlin { // destinationDirectory = project.layout.buildDirectory.dir("kotlin-js-min") //} -rootProject.plugins.withType(org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin) { - def kotlinNodeJs = rootProject.extensions.getByType(org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension) - - tasks.register("runWebpack", Exec) { - dependsOn(tasks.named('browserProductionWebpack')) - - executable(kotlinNodeJs.requireConfigured().executable) - - workingDir = "${rootProject.buildDir}/js/packages/kotlin-js-dce-mainProject" - args = ["../../node_modules/webpack/bin/webpack.js"] - } - - tasks.named("assemble") { - dependsOn("runWebpack") - } -} - tasks.register('runRhino', JavaExec) { diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-wasm-test/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-wasm-test/build.gradle.kts index d98574fcc95da..b34ee25ea12b1 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-wasm-test/build.gradle.kts +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-wasm-test/build.gradle.kts @@ -7,7 +7,7 @@ repositories { mavenCentral() } -with(org.jetbrains.kotlin.gradle.targets.js.d8.D8RootPlugin.apply(rootProject)) { +with(org.jetbrains.kotlin.gradle.targets.js.d8.D8Plugin.apply(rootProject)) { // Test that we can set the version and it is a String. // But use the default version since update this place every time anyway. version = (version as String) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-wasm-wasi-js-test/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-wasm-wasi-js-test/build.gradle.kts index 0e04c1ca0b618..01f933672dd30 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-wasm-wasi-js-test/build.gradle.kts +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-wasm-wasi-js-test/build.gradle.kts @@ -11,10 +11,10 @@ rootProject.plugins.withType { +rootProject.plugins.withType { // Test that we can set the version and it is a String. // But use the default version since update this place every time anyway. - rootProject.the().version = (version as String) + rootProject.the().version = (version as String) } allprojects { diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-wasm-wasi-test/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-wasm-wasi-test/build.gradle.kts index 1ff492acf452c..0038899e41656 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-wasm-wasi-test/build.gradle.kts +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-wasm-wasi-test/build.gradle.kts @@ -2,7 +2,7 @@ plugins { kotlin("multiplatform") } -with(org.jetbrains.kotlin.gradle.targets.js.d8.D8RootPlugin.apply(rootProject)) { +with(org.jetbrains.kotlin.gradle.targets.js.d8.D8Plugin.apply(rootProject)) { // Test that we can set the version and it is a String. // But use the default version since update this place every time anyway. version = (version as String) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/subprojects-nodejs-setup/app1/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/subprojects-nodejs-setup/app1/build.gradle.kts new file mode 100644 index 0000000000000..d9ae9430b0ef6 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/subprojects-nodejs-setup/app1/build.gradle.kts @@ -0,0 +1,14 @@ +plugins { + id("org.jetbrains.kotlin.multiplatform") +} + +kotlin { + js { + binaries.executable() + nodejs() + } +} + +plugins.withType { + the().version.set("22.2.0") +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/subprojects-nodejs-setup/app1/src/jsMain/kotlin/main.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/subprojects-nodejs-setup/app1/src/jsMain/kotlin/main.kt new file mode 100644 index 0000000000000..920a1f2f377ff --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/subprojects-nodejs-setup/app1/src/jsMain/kotlin/main.kt @@ -0,0 +1,10 @@ +/* + * Copyright 2010-2024 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. + */ + +fun main() { + println("Hello with version: " + process.version) +} + +external val process: dynamic \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/subprojects-nodejs-setup/app2/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/subprojects-nodejs-setup/app2/build.gradle.kts new file mode 100644 index 0000000000000..50e67a0460f5c --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/subprojects-nodejs-setup/app2/build.gradle.kts @@ -0,0 +1,14 @@ +plugins { + id("org.jetbrains.kotlin.multiplatform") +} + +kotlin { + js { + binaries.executable() + nodejs() + } +} + +plugins.withType { + the().version.set("22.1.0") +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/subprojects-nodejs-setup/app2/src/jsMain/kotlin/foo.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/subprojects-nodejs-setup/app2/src/jsMain/kotlin/foo.kt new file mode 100644 index 0000000000000..920a1f2f377ff --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/subprojects-nodejs-setup/app2/src/jsMain/kotlin/foo.kt @@ -0,0 +1,10 @@ +/* + * Copyright 2010-2024 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. + */ + +fun main() { + println("Hello with version: " + process.version) +} + +external val process: dynamic \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/subprojects-nodejs-setup/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/subprojects-nodejs-setup/build.gradle.kts new file mode 100644 index 0000000000000..c73eafb494428 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/subprojects-nodejs-setup/build.gradle.kts @@ -0,0 +1,3 @@ +plugins { + id("org.jetbrains.kotlin.multiplatform") apply false +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/subprojects-nodejs-setup/settings.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/subprojects-nodejs-setup/settings.gradle.kts new file mode 100644 index 0000000000000..bfff566442de5 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/subprojects-nodejs-setup/settings.gradle.kts @@ -0,0 +1,2 @@ +include("app1") +include("app2") \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/wasm-wasi-js-with-wasi-only-dependency/build.gradle.kts b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/wasm-wasi-js-with-wasi-only-dependency/build.gradle.kts index 0e04c1ca0b618..01f933672dd30 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/wasm-wasi-js-with-wasi-only-dependency/build.gradle.kts +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/wasm-wasi-js-with-wasi-only-dependency/build.gradle.kts @@ -11,10 +11,10 @@ rootProject.plugins.withType { +rootProject.plugins.withType { // Test that we can set the version and it is a String. // But use the default version since update this place every time anyway. - rootProject.the().version = (version as String) + rootProject.the().version = (version as String) } allprojects { diff --git a/libraries/tools/kotlin-gradle-plugin/api/all/kotlin-gradle-plugin.api b/libraries/tools/kotlin-gradle-plugin/api/all/kotlin-gradle-plugin.api index 516f40a7464fb..dbd1fc998ced1 100644 --- a/libraries/tools/kotlin-gradle-plugin/api/all/kotlin-gradle-plugin.api +++ b/libraries/tools/kotlin-gradle-plugin/api/all/kotlin-gradle-plugin.api @@ -3011,22 +3011,22 @@ public abstract interface class org/jetbrains/kotlin/gradle/targets/js/AbstractE public abstract class org/jetbrains/kotlin/gradle/targets/js/AbstractSettings : org/jetbrains/kotlin/gradle/internal/ConfigurationPhaseAware { public fun ()V - public abstract fun getCommand ()Ljava/lang/String; - public abstract fun getDownload ()Z - public abstract fun getDownloadBaseUrl ()Ljava/lang/String; - public abstract fun getInstallationDir ()Ljava/io/File; - public abstract fun getVersion ()Ljava/lang/String; - public abstract fun setCommand (Ljava/lang/String;)V - public abstract fun setDownload (Z)V - public abstract fun setDownloadBaseUrl (Ljava/lang/String;)V - public abstract fun setInstallationDir (Ljava/io/File;)V - public abstract fun setVersion (Ljava/lang/String;)V + public final fun getCommand ()Ljava/lang/String; + public final fun getDownload ()Z + public final fun getDownloadBaseUrl ()Ljava/lang/String; + public final fun getInstallationDir ()Ljava/io/File; + public final fun getVersion ()Ljava/lang/String; + public final fun setCommand (Ljava/lang/String;)V + public final fun setDownload (Z)V + public final fun setDownloadBaseUrl (Ljava/lang/String;)V + public final fun setInstallationDir (Ljava/io/File;)V + public final fun setVersion (Ljava/lang/String;)V } public abstract class org/jetbrains/kotlin/gradle/targets/js/AbstractSetupTask : org/gradle/api/DefaultTask, org/jetbrains/kotlin/gradle/plugin/statistics/UsesBuildFusService { public static final field CACHE_VERSION Ljava/lang/String; public static final field Companion Lorg/jetbrains/kotlin/gradle/targets/js/AbstractSetupTask$Companion; - public fun ()V + public fun (Lorg/jetbrains/kotlin/gradle/targets/js/EnvSpec;)V public final fun exec ()V public abstract fun extract (Ljava/io/File;)V protected abstract fun getArtifactModule ()Ljava/lang/String; @@ -3034,16 +3034,26 @@ public abstract class org/jetbrains/kotlin/gradle/targets/js/AbstractSetupTask : protected abstract fun getArtifactPattern ()Ljava/lang/String; public final fun getDestination ()Ljava/io/File; public final fun getDestinationHashFile ()Ljava/io/File; + public final fun getDestinationHashFileProvider ()Lorg/gradle/api/file/RegularFileProperty; public final fun getDist ()Ljava/io/File; public final fun getDownloadBaseUrl ()Ljava/lang/String; - protected final fun getEnv ()Lorg/jetbrains/kotlin/gradle/targets/js/AbstractEnv; + public final fun getDownloadBaseUrlProvider ()Lorg/gradle/api/provider/Provider; + protected final fun getEnv ()Lorg/gradle/api/provider/Provider; public final fun getIvyDependency ()Ljava/lang/String; - protected abstract fun getSettings ()Lorg/jetbrains/kotlin/gradle/targets/js/AbstractSettings; } public final class org/jetbrains/kotlin/gradle/targets/js/AbstractSetupTask$Companion { } +public abstract class org/jetbrains/kotlin/gradle/targets/js/EnvSpec { + public fun ()V + public abstract fun getCommand ()Lorg/gradle/api/provider/Property; + public abstract fun getDownload ()Lorg/gradle/api/provider/Property; + public abstract fun getDownloadBaseUrl ()Lorg/gradle/api/provider/Property; + public abstract fun getInstallationDirectory ()Lorg/gradle/api/file/DirectoryProperty; + public abstract fun getVersion ()Lorg/gradle/api/provider/Property; +} + public final class org/jetbrains/kotlin/gradle/targets/js/JsAggregatingExecutionSource : org/jetbrains/kotlin/gradle/execution/KotlinAggregateExecutionSource { public fun (Lorg/jetbrains/kotlin/gradle/targets/js/KotlinJsReportAggregatingTestRun;)V public fun getExecutionSources ()Ljava/lang/Iterable; @@ -3248,24 +3258,23 @@ public final class org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenExec$ public static synthetic fun create$default (Lorg/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenExec$Companion;Lorg/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrCompilation;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/gradle/api/tasks/TaskProvider; } +public abstract class org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenRootEnvSpec : org/jetbrains/kotlin/gradle/targets/js/EnvSpec { + public static final field Companion Lorg/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenRootEnvSpec$Companion; + public static final field EXTENSION_NAME Ljava/lang/String; + public fun ()V +} + +public final class org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenRootEnvSpec$Companion { +} + public class org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenRootExtension : org/jetbrains/kotlin/gradle/targets/js/AbstractSettings { public static final field Companion Lorg/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenRootExtension$Companion; public static final field EXTENSION_NAME Ljava/lang/String; - public fun (Lorg/gradle/api/Project;)V + public fun (Lorg/gradle/api/Project;Lorg/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenRootEnvSpec;)V public synthetic fun finalizeConfiguration ()Ljava/lang/Object; protected fun finalizeConfiguration ()Lorg/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenEnv; - public fun getCommand ()Ljava/lang/String; - public fun getDownload ()Z - public fun getDownloadBaseUrl ()Ljava/lang/String; - public fun getInstallationDir ()Ljava/io/File; public final fun getRootProject ()Lorg/gradle/api/Project; public final fun getSetupTaskProvider ()Lorg/gradle/api/tasks/TaskProvider; - public fun getVersion ()Ljava/lang/String; - public fun setCommand (Ljava/lang/String;)V - public fun setDownload (Z)V - public fun setDownloadBaseUrl (Ljava/lang/String;)V - public fun setInstallationDir (Ljava/io/File;)V - public fun setVersion (Ljava/lang/String;)V } public final class org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenRootExtension$Companion { @@ -3287,13 +3296,10 @@ public final class org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenRootP public abstract class org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenSetupTask : org/jetbrains/kotlin/gradle/targets/js/AbstractSetupTask { public static final field Companion Lorg/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenSetupTask$Companion; public static final field NAME Ljava/lang/String; - public fun ()V public fun extract (Ljava/io/File;)V protected fun getArtifactModule ()Ljava/lang/String; protected fun getArtifactName ()Ljava/lang/String; protected fun getArtifactPattern ()Ljava/lang/String; - public synthetic fun getSettings ()Lorg/jetbrains/kotlin/gradle/targets/js/AbstractSettings; - protected fun getSettings ()Lorg/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenRootExtension; } public final class org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenSetupTask$Companion { @@ -3323,6 +3329,17 @@ public final class org/jetbrains/kotlin/gradle/targets/js/d8/D8Env : org/jetbrai public fun toString ()Ljava/lang/String; } +public abstract class org/jetbrains/kotlin/gradle/targets/js/d8/D8EnvSpec : org/jetbrains/kotlin/gradle/targets/js/EnvSpec { + public static final field Companion Lorg/jetbrains/kotlin/gradle/targets/js/d8/D8EnvSpec$Companion; + public static final field EXTENSION_NAME Ljava/lang/String; + public fun ()V + public abstract fun getEdition ()Lorg/gradle/api/provider/Property; + public abstract fun getVersion ()Lorg/gradle/api/provider/Property; +} + +public final class org/jetbrains/kotlin/gradle/targets/js/d8/D8EnvSpec$Companion { +} + public class org/jetbrains/kotlin/gradle/targets/js/d8/D8Exec : org/gradle/api/tasks/AbstractExecTask { public static final field Companion Lorg/jetbrains/kotlin/gradle/targets/js/d8/D8Exec$Companion; public fun ()V @@ -3337,54 +3354,40 @@ public final class org/jetbrains/kotlin/gradle/targets/js/d8/D8Exec$Companion { public static synthetic fun create$default (Lorg/jetbrains/kotlin/gradle/targets/js/d8/D8Exec$Companion;Lorg/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrCompilation;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/gradle/api/tasks/TaskProvider; } -public class org/jetbrains/kotlin/gradle/targets/js/d8/D8RootExtension : org/jetbrains/kotlin/gradle/targets/js/AbstractSettings { - public static final field Companion Lorg/jetbrains/kotlin/gradle/targets/js/d8/D8RootExtension$Companion; +public class org/jetbrains/kotlin/gradle/targets/js/d8/D8Extension : org/jetbrains/kotlin/gradle/targets/js/AbstractSettings { + public static final field Companion Lorg/jetbrains/kotlin/gradle/targets/js/d8/D8Extension$Companion; public static final field EXTENSION_NAME Ljava/lang/String; - public fun (Lorg/gradle/api/Project;)V + public fun (Lorg/gradle/api/Project;Lorg/jetbrains/kotlin/gradle/targets/js/d8/D8EnvSpec;)V public synthetic fun finalizeConfiguration ()Ljava/lang/Object; protected fun finalizeConfiguration ()Lorg/jetbrains/kotlin/gradle/targets/js/d8/D8Env; - public fun getCommand ()Ljava/lang/String; - public fun getDownload ()Z - public fun getDownloadBaseUrl ()Ljava/lang/String; - public final fun getEdition ()Ljava/lang/String; - public fun getInstallationDir ()Ljava/io/File; - public final fun getRootProject ()Lorg/gradle/api/Project; + public final fun getEdition ()Lorg/gradle/api/provider/Property; + public final fun getProject ()Lorg/gradle/api/Project; public final fun getSetupTaskProvider ()Lorg/gradle/api/tasks/TaskProvider; - public fun getVersion ()Ljava/lang/String; - public fun setCommand (Ljava/lang/String;)V - public fun setDownload (Z)V - public fun setDownloadBaseUrl (Ljava/lang/String;)V - public final fun setEdition (Ljava/lang/String;)V - public fun setInstallationDir (Ljava/io/File;)V - public fun setVersion (Ljava/lang/String;)V } -public final class org/jetbrains/kotlin/gradle/targets/js/d8/D8RootExtension$Companion { +public final class org/jetbrains/kotlin/gradle/targets/js/d8/D8Extension$Companion { } -public class org/jetbrains/kotlin/gradle/targets/js/d8/D8RootPlugin : org/gradle/api/Plugin { - public static final field Companion Lorg/jetbrains/kotlin/gradle/targets/js/d8/D8RootPlugin$Companion; +public class org/jetbrains/kotlin/gradle/targets/js/d8/D8Plugin : org/gradle/api/Plugin { + public static final field Companion Lorg/jetbrains/kotlin/gradle/targets/js/d8/D8Plugin$Companion; public static final field TASKS_GROUP_NAME Ljava/lang/String; public fun ()V public synthetic fun apply (Ljava/lang/Object;)V public fun apply (Lorg/gradle/api/Project;)V } -public final class org/jetbrains/kotlin/gradle/targets/js/d8/D8RootPlugin$Companion { - public final fun apply (Lorg/gradle/api/Project;)Lorg/jetbrains/kotlin/gradle/targets/js/d8/D8RootExtension; - public final fun getKotlinD8Extension (Lorg/gradle/api/Project;)Lorg/jetbrains/kotlin/gradle/targets/js/d8/D8RootExtension; +public final class org/jetbrains/kotlin/gradle/targets/js/d8/D8Plugin$Companion { + public final fun apply (Lorg/gradle/api/Project;)Lorg/jetbrains/kotlin/gradle/targets/js/d8/D8Extension; } public abstract class org/jetbrains/kotlin/gradle/targets/js/d8/D8SetupTask : org/jetbrains/kotlin/gradle/targets/js/AbstractSetupTask { public static final field Companion Lorg/jetbrains/kotlin/gradle/targets/js/d8/D8SetupTask$Companion; public static final field NAME Ljava/lang/String; - public fun ()V + public fun (Lorg/jetbrains/kotlin/gradle/targets/js/d8/D8EnvSpec;)V public fun extract (Ljava/io/File;)V protected fun getArtifactModule ()Ljava/lang/String; protected fun getArtifactName ()Ljava/lang/String; protected fun getArtifactPattern ()Ljava/lang/String; - public synthetic fun getSettings ()Lorg/jetbrains/kotlin/gradle/targets/js/AbstractSettings; - protected fun getSettings ()Lorg/jetbrains/kotlin/gradle/targets/js/d8/D8RootExtension; } public final class org/jetbrains/kotlin/gradle/targets/js/d8/D8SetupTask$Companion { @@ -4033,20 +4036,18 @@ public final class org/jetbrains/kotlin/gradle/targets/js/ir/OutputGranularityKt } public final class org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsEnv : org/jetbrains/kotlin/gradle/targets/js/AbstractEnv { - public fun (ZLorg/jetbrains/kotlin/gradle/tasks/internal/CleanableStore;Ljava/io/File;Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lorg/jetbrains/kotlin/gradle/targets/js/npm/NpmApiExecution;)V + public fun (ZLorg/jetbrains/kotlin/gradle/tasks/internal/CleanableStore;Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V public final fun component1 ()Z - public final fun component10 ()Ljava/lang/String; - public final fun component11 ()Lorg/jetbrains/kotlin/gradle/targets/js/npm/NpmApiExecution; public final fun component2 ()Lorg/jetbrains/kotlin/gradle/tasks/internal/CleanableStore; public final fun component3 ()Ljava/io/File; public final fun component4 ()Ljava/io/File; - public final fun component5 ()Ljava/io/File; + public final fun component5 ()Ljava/lang/String; public final fun component6 ()Ljava/lang/String; public final fun component7 ()Ljava/lang/String; public final fun component8 ()Ljava/lang/String; public final fun component9 ()Ljava/lang/String; - public final fun copy (ZLorg/jetbrains/kotlin/gradle/tasks/internal/CleanableStore;Ljava/io/File;Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lorg/jetbrains/kotlin/gradle/targets/js/npm/NpmApiExecution;)Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsEnv; - public static synthetic fun copy$default (Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsEnv;ZLorg/jetbrains/kotlin/gradle/tasks/internal/CleanableStore;Ljava/io/File;Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lorg/jetbrains/kotlin/gradle/targets/js/npm/NpmApiExecution;ILjava/lang/Object;)Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsEnv; + public final fun copy (ZLorg/jetbrains/kotlin/gradle/tasks/internal/CleanableStore;Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsEnv; + public static synthetic fun copy$default (Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsEnv;ZLorg/jetbrains/kotlin/gradle/tasks/internal/CleanableStore;Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsEnv; public fun equals (Ljava/lang/Object;)Z public final fun getArchitectureName ()Ljava/lang/String; public fun getCleanableStore ()Lorg/jetbrains/kotlin/gradle/tasks/internal/CleanableStore; @@ -4057,28 +4058,36 @@ public final class org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsEnv : org public fun getIvyDependency ()Ljava/lang/String; public final fun getNodeBinDir ()Ljava/io/File; public final fun getNodeExecutable ()Ljava/lang/String; - public final fun getPackageManager ()Lorg/jetbrains/kotlin/gradle/targets/js/npm/NpmApiExecution; public final fun getPlatformName ()Ljava/lang/String; - public final fun getRootPackageDir ()Ljava/io/File; public fun hashCode ()I public final fun isWindows ()Z public fun toString ()Ljava/lang/String; } +public abstract class org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsEnvSpec : org/jetbrains/kotlin/gradle/targets/js/EnvSpec { + public static final field Companion Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsEnvSpec$Companion; + public static final field EXTENSION_NAME Ljava/lang/String; + public fun ()V + public final fun getNodeJsSetupTaskProvider (Lorg/gradle/api/Project;)Lorg/gradle/api/tasks/TaskProvider; +} + +public final class org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsEnvSpec$Companion { +} + public class org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsExec : org/gradle/api/tasks/AbstractExecTask, org/jetbrains/kotlin/gradle/targets/js/npm/RequiresNpmDependencies { public static final field Companion Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsExec$Companion; - public field nodeJs Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootExtension; + public field nodeJsRoot Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootExtension; public fun (Lorg/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrCompilation;)V protected fun exec ()V public final fun getCompilation ()Lorg/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrCompilation; public final fun getInputFileProperty ()Lorg/gradle/api/file/RegularFileProperty; public final fun getNodeArgs ()Ljava/util/List; - public final fun getNodeJs ()Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootExtension; + public final fun getNodeJsRoot ()Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootExtension; public final fun getNpmProject ()Lorg/jetbrains/kotlin/gradle/targets/js/npm/NpmProject; public fun getRequiredNpmDependencies ()Ljava/util/Set; public final fun getSourceMapStackTraces ()Z public final fun setNodeArgs (Ljava/util/List;)V - public final fun setNodeJs (Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootExtension;)V + public final fun setNodeJsRoot (Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootExtension;)V public final fun setSourceMapStackTraces (Z)V } @@ -4089,21 +4098,31 @@ public final class org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsExec$Comp public static synthetic fun create$default (Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsExec$Companion;Lorg/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrCompilation;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lorg/gradle/api/tasks/TaskProvider; } -public class org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootExtension : org/jetbrains/kotlin/gradle/targets/js/AbstractSettings { +public class org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsPlugin : org/gradle/api/Plugin { + public static final field Companion Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsPlugin$Companion; + public static final field TASKS_GROUP_NAME Ljava/lang/String; + public fun ()V + public synthetic fun apply (Ljava/lang/Object;)V + public fun apply (Lorg/gradle/api/Project;)V +} + +public final class org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsPlugin$Companion { + public final fun apply (Lorg/gradle/api/Project;)Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsEnvSpec; + public final fun getKotlinNodeJsEnvSpec (Lorg/gradle/api/Project;)Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsEnvSpec; +} + +public class org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootExtension { public static final field Companion Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootExtension$Companion; public static final field EXTENSION_NAME Ljava/lang/String; public field resolver Lorg/jetbrains/kotlin/gradle/targets/js/npm/resolver/KotlinRootNpmResolver; - public fun (Lorg/gradle/api/Project;)V - public synthetic fun finalizeConfiguration ()Ljava/lang/Object; - protected fun finalizeConfiguration ()Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsEnv; - public fun getCommand ()Ljava/lang/String; - public fun getDownload ()Z - public fun getDownloadBaseUrl ()Ljava/lang/String; - public fun getInstallationDir ()Ljava/io/File; + public fun (Lorg/gradle/api/Project;Lkotlin/jvm/functions/Function0;)V + public final fun getCommand ()Ljava/lang/String; + public final fun getDownload ()Z + public final fun getDownloadBaseUrl ()Ljava/lang/String; + public final fun getInstallationDir ()Ljava/io/File; public final fun getNodeCommand ()Ljava/lang/String; public final fun getNodeDownloadBaseUrl ()Ljava/lang/String; public final fun getNodeJsSetupTaskProvider ()Lorg/gradle/api/tasks/TaskProvider; - public final fun getNodeModulesGradleCacheDir ()Ljava/io/File; public final fun getNodeModulesGradleCacheDirectory ()Lorg/gradle/api/provider/Provider; public final fun getNodeVersion ()Ljava/lang/String; public final fun getNpmCachesSetupTaskProvider ()Lorg/gradle/api/tasks/TaskProvider; @@ -4111,26 +4130,24 @@ public class org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootExtension : public final fun getPackageJsonUmbrellaTaskProvider ()Lorg/gradle/api/tasks/TaskProvider; public final fun getPackageManagerExtension ()Lorg/gradle/api/provider/Property; public final fun getProject ()Lorg/gradle/api/Project; - public final fun getProjectPackagesDir ()Ljava/io/File; public final fun getProjectPackagesDirectory ()Lorg/gradle/api/provider/Provider; public final fun getResolver ()Lorg/jetbrains/kotlin/gradle/targets/js/npm/resolver/KotlinRootNpmResolver; - public final fun getRootPackageDir ()Ljava/io/File; public final fun getRootPackageDirectory ()Lorg/gradle/api/provider/Provider; public final fun getRootPackageJsonTaskProvider ()Lorg/gradle/api/tasks/TaskProvider; public final fun getRootProjectDir ()Ljava/io/File; - public final fun getStoreYarnLockTaskProvider ()Lorg/gradle/api/tasks/TaskProvider; public final fun getTaskRequirements ()Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/TasksRequirements; - public fun getVersion ()Ljava/lang/String; + public final fun getVersion ()Ljava/lang/String; public final fun getVersions ()Lorg/jetbrains/kotlin/gradle/targets/js/NpmVersions; - public fun setCommand (Ljava/lang/String;)V - public fun setDownload (Z)V - public fun setDownloadBaseUrl (Ljava/lang/String;)V - public fun setInstallationDir (Ljava/io/File;)V + public final fun requireConfigured ()Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsEnv; + public final fun setCommand (Ljava/lang/String;)V + public final fun setDownload (Z)V + public final fun setDownloadBaseUrl (Ljava/lang/String;)V + public final fun setInstallationDir (Ljava/io/File;)V public final fun setNodeCommand (Ljava/lang/String;)V public final fun setNodeDownloadBaseUrl (Ljava/lang/String;)V public final fun setNodeVersion (Ljava/lang/String;)V public final fun setResolver (Lorg/jetbrains/kotlin/gradle/targets/js/npm/resolver/KotlinRootNpmResolver;)V - public fun setVersion (Ljava/lang/String;)V + public final fun setVersion (Ljava/lang/String;)V } public final class org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootExtension$Companion { @@ -4146,20 +4163,18 @@ public class org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootPlugin : or public final class org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootPlugin$Companion { public final fun apply (Lorg/gradle/api/Project;)Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootExtension; - public final fun getKotlinNodeJsExtension (Lorg/gradle/api/Project;)Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootExtension; + public final fun getKotlinNodeJsRootExtension (Lorg/gradle/api/Project;)Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootExtension; public final fun getKotlinNpmResolutionManager (Lorg/gradle/api/Project;)Lorg/gradle/api/provider/Provider; } public abstract class org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsSetupTask : org/jetbrains/kotlin/gradle/targets/js/AbstractSetupTask { public static final field Companion Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsSetupTask$Companion; public static final field NAME Ljava/lang/String; - public fun ()V + public fun (Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsEnvSpec;)V public fun extract (Ljava/io/File;)V protected fun getArtifactModule ()Ljava/lang/String; protected fun getArtifactName ()Ljava/lang/String; protected fun getArtifactPattern ()Ljava/lang/String; - public synthetic fun getSettings ()Lorg/jetbrains/kotlin/gradle/targets/js/AbstractSettings; - protected fun getSettings ()Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootExtension; } public final class org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsSetupTask$Companion { @@ -4325,16 +4340,16 @@ public abstract class org/jetbrains/kotlin/gradle/targets/js/npm/LockStoreTask : } public final class org/jetbrains/kotlin/gradle/targets/js/npm/NodeJsEnvironment : java/io/Serializable { - public fun (Ljava/io/File;Ljava/lang/String;Lorg/jetbrains/kotlin/gradle/targets/js/npm/NpmApiExecution;)V - public final fun component1 ()Ljava/io/File; + public fun (Lorg/gradle/api/provider/Provider;Ljava/lang/String;Lorg/jetbrains/kotlin/gradle/targets/js/npm/NpmApiExecution;)V + public final fun component1 ()Lorg/gradle/api/provider/Provider; public final fun component2 ()Ljava/lang/String; public final fun component3 ()Lorg/jetbrains/kotlin/gradle/targets/js/npm/NpmApiExecution; - public final fun copy (Ljava/io/File;Ljava/lang/String;Lorg/jetbrains/kotlin/gradle/targets/js/npm/NpmApiExecution;)Lorg/jetbrains/kotlin/gradle/targets/js/npm/NodeJsEnvironment; - public static synthetic fun copy$default (Lorg/jetbrains/kotlin/gradle/targets/js/npm/NodeJsEnvironment;Ljava/io/File;Ljava/lang/String;Lorg/jetbrains/kotlin/gradle/targets/js/npm/NpmApiExecution;ILjava/lang/Object;)Lorg/jetbrains/kotlin/gradle/targets/js/npm/NodeJsEnvironment; + public final fun copy (Lorg/gradle/api/provider/Provider;Ljava/lang/String;Lorg/jetbrains/kotlin/gradle/targets/js/npm/NpmApiExecution;)Lorg/jetbrains/kotlin/gradle/targets/js/npm/NodeJsEnvironment; + public static synthetic fun copy$default (Lorg/jetbrains/kotlin/gradle/targets/js/npm/NodeJsEnvironment;Lorg/gradle/api/provider/Provider;Ljava/lang/String;Lorg/jetbrains/kotlin/gradle/targets/js/npm/NpmApiExecution;ILjava/lang/Object;)Lorg/jetbrains/kotlin/gradle/targets/js/npm/NodeJsEnvironment; public fun equals (Ljava/lang/Object;)Z public final fun getNodeExecutable ()Ljava/lang/String; public final fun getPackageManager ()Lorg/jetbrains/kotlin/gradle/targets/js/npm/NpmApiExecution; - public final fun getRootPackageDir ()Ljava/io/File; + public final fun getRootPackageDir ()Lorg/gradle/api/provider/Provider; public fun hashCode ()I public fun toString ()Ljava/lang/String; } @@ -4479,7 +4494,7 @@ public final class org/jetbrains/kotlin/gradle/targets/js/npm/NpmEnvironment : o public class org/jetbrains/kotlin/gradle/targets/js/npm/NpmExtension : org/jetbrains/kotlin/gradle/internal/ConfigurationPhaseAware, org/jetbrains/kotlin/gradle/targets/js/nodejs/NpmApiExtension { public static final field Companion Lorg/jetbrains/kotlin/gradle/targets/js/npm/NpmExtension$Companion; public static final field EXTENSION_NAME Ljava/lang/String; - public fun (Lorg/gradle/api/Project;)V + public fun (Lorg/gradle/api/Project;Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootExtension;)V public synthetic fun finalizeConfiguration ()Ljava/lang/Object; protected fun finalizeConfiguration ()Lorg/jetbrains/kotlin/gradle/targets/js/npm/NpmEnv; public fun getAdditionalInstallOutput ()Lorg/gradle/api/file/FileCollection; @@ -4489,6 +4504,7 @@ public class org/jetbrains/kotlin/gradle/targets/js/npm/NpmExtension : org/jetbr public final fun getIgnoreScripts ()Lorg/gradle/api/provider/Property; public final fun getLockFileDirectory ()Lorg/gradle/api/file/DirectoryProperty; public final fun getLockFileName ()Lorg/gradle/api/provider/Property; + public final fun getNodeJsRoot ()Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootExtension; public final fun getOverrides ()Lorg/gradle/api/provider/ListProperty; public final fun getPackageLockAutoReplace ()Lorg/gradle/api/provider/Property; public final fun getPackageLockMismatchReport ()Lorg/gradle/api/provider/Property; @@ -4540,7 +4556,8 @@ public class org/jetbrains/kotlin/gradle/targets/js/npm/NpmProject : java/io/Ser public final fun getDist ()Lorg/gradle/api/provider/Provider; public final fun getMain ()Lorg/gradle/api/provider/Provider; public final fun getName ()Ljava/lang/String; - public final fun getNodeJs ()Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootExtension; + public final fun getNodeJs ()Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsEnvSpec; + public final fun getNodeJsRoot ()Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootExtension; public final fun getNodeModulesDir ()Lorg/gradle/api/provider/Provider; public final fun getPackageJsonFile ()Lorg/gradle/api/provider/Provider; public final fun getPackageJsonTask ()Lorg/jetbrains/kotlin/gradle/targets/js/npm/tasks/KotlinPackageJsonTask; @@ -5800,22 +5817,33 @@ public final class org/jetbrains/kotlin/gradle/targets/js/yarn/YarnResolutionsKt public static final fun toVersionString (Lorg/jetbrains/kotlin/gradle/targets/js/yarn/YarnResolution;)Ljava/lang/String; } +public abstract class org/jetbrains/kotlin/gradle/targets/js/yarn/YarnRootEnvSpec : org/jetbrains/kotlin/gradle/targets/js/EnvSpec { + public static final field Companion Lorg/jetbrains/kotlin/gradle/targets/js/yarn/YarnRootEnvSpec$Companion; + public static final field YARN Ljava/lang/String; + public fun ()V + public abstract fun getIgnoreScripts ()Lorg/gradle/api/provider/Property; + public abstract fun getReportNewYarnLock ()Lorg/gradle/api/provider/Property; + public abstract fun getResolutions ()Lorg/gradle/api/provider/ListProperty; + public abstract fun getYarnLockAutoReplace ()Lorg/gradle/api/provider/Property; + public abstract fun getYarnLockMismatchReport ()Lorg/gradle/api/provider/Property; +} + +public final class org/jetbrains/kotlin/gradle/targets/js/yarn/YarnRootEnvSpec$Companion { +} + public class org/jetbrains/kotlin/gradle/targets/js/yarn/YarnRootExtension : org/jetbrains/kotlin/gradle/targets/js/AbstractSettings, org/jetbrains/kotlin/gradle/targets/js/nodejs/NpmApiExtension { public static final field Companion Lorg/jetbrains/kotlin/gradle/targets/js/yarn/YarnRootExtension$Companion; public static final field YARN Ljava/lang/String; - public fun (Lorg/gradle/api/Project;)V + public fun (Lorg/gradle/api/Project;Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootExtension;Lorg/jetbrains/kotlin/gradle/targets/js/yarn/YarnRootEnvSpec;)V public synthetic fun finalizeConfiguration ()Ljava/lang/Object; protected fun finalizeConfiguration ()Lorg/jetbrains/kotlin/gradle/targets/js/yarn/YarnEnv; public fun getAdditionalInstallOutput ()Lorg/gradle/api/file/FileCollection; - public fun getCommand ()Ljava/lang/String; - public fun getDownload ()Z - public fun getDownloadBaseUrl ()Ljava/lang/String; public synthetic fun getEnvironment ()Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/PackageManagerEnvironment; public fun getEnvironment ()Lorg/jetbrains/kotlin/gradle/targets/js/yarn/YarnEnvironment; public final fun getIgnoreScripts ()Z - public fun getInstallationDir ()Ljava/io/File; public final fun getLockFileDirectory ()Ljava/io/File; public final fun getLockFileName ()Ljava/lang/String; + public final fun getNodeJsRoot ()Lorg/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootExtension; public synthetic fun getPackageManager ()Lorg/jetbrains/kotlin/gradle/targets/js/npm/NpmApiExecution; public fun getPackageManager ()Lorg/jetbrains/kotlin/gradle/targets/js/yarn/Yarn; public fun getPostInstallTasks ()Lorg/gradle/api/provider/ListProperty; @@ -5825,22 +5853,16 @@ public class org/jetbrains/kotlin/gradle/targets/js/yarn/YarnRootExtension : org public final fun getResolutions ()Ljava/util/List; public final fun getRestoreYarnLockTaskProvider ()Lorg/gradle/api/tasks/TaskProvider; public final fun getStoreYarnLockTaskProvider ()Lorg/gradle/api/tasks/TaskProvider; - public fun getVersion ()Ljava/lang/String; public final fun getYarnLockAutoReplace ()Z public final fun getYarnLockMismatchReport ()Lorg/jetbrains/kotlin/gradle/targets/js/yarn/YarnLockMismatchReport; public final fun getYarnSetupTaskProvider ()Lorg/gradle/api/tasks/TaskProvider; public final fun resolution (Ljava/lang/String;Ljava/lang/String;)V public final fun resolution (Ljava/lang/String;Lorg/gradle/api/Action;)V - public fun setCommand (Ljava/lang/String;)V - public fun setDownload (Z)V - public fun setDownloadBaseUrl (Ljava/lang/String;)V public final fun setIgnoreScripts (Z)V - public fun setInstallationDir (Ljava/io/File;)V public final fun setLockFileDirectory (Ljava/io/File;)V public final fun setLockFileName (Ljava/lang/String;)V public final fun setReportNewYarnLock (Z)V public final fun setResolutions (Ljava/util/List;)V - public fun setVersion (Ljava/lang/String;)V public final fun setYarnLockAutoReplace (Z)V public final fun setYarnLockMismatchReport (Lorg/jetbrains/kotlin/gradle/targets/js/yarn/YarnLockMismatchReport;)V } @@ -5856,13 +5878,11 @@ public final class org/jetbrains/kotlin/gradle/targets/js/yarn/YarnRootExtension public abstract class org/jetbrains/kotlin/gradle/targets/js/yarn/YarnSetupTask : org/jetbrains/kotlin/gradle/targets/js/AbstractSetupTask { public static final field Companion Lorg/jetbrains/kotlin/gradle/targets/js/yarn/YarnSetupTask$Companion; public static final field NAME Ljava/lang/String; - public fun ()V + public fun (Lorg/jetbrains/kotlin/gradle/targets/js/yarn/YarnRootEnvSpec;)V public fun extract (Ljava/io/File;)V protected fun getArtifactModule ()Ljava/lang/String; protected fun getArtifactName ()Ljava/lang/String; protected fun getArtifactPattern ()Ljava/lang/String; - public synthetic fun getSettings ()Lorg/jetbrains/kotlin/gradle/targets/js/AbstractSettings; - protected fun getSettings ()Lorg/jetbrains/kotlin/gradle/targets/js/yarn/YarnRootExtension; } public final class org/jetbrains/kotlin/gradle/targets/js/yarn/YarnSetupTask$Companion { diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/AbstractEnvSpec.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/AbstractEnvSpec.kt new file mode 100644 index 0000000000000..6da821a147cce --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/AbstractEnvSpec.kt @@ -0,0 +1,47 @@ +package org.jetbrains.kotlin.gradle.targets.js + +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.provider.Property +import org.gradle.api.provider.Provider +import org.gradle.api.provider.ProviderFactory + +/** + * Instance which describes specific runtimes for JS and Wasm targets + * + * It encapsulates necessary information about a tool to run application and tests + */ +abstract class EnvSpec { + + /** + * Specify whether we need to download the tool + */ + abstract val download: Property + + /** + * Specify url to add repository from which the tool is going to be downloaded + * + * If the property has no value, repository is not added, + * so this can be used to add your own repository where the tool is located + */ + abstract val downloadBaseUrl: Property + + /** + * Specify where the tool is installed + */ + abstract val installationDirectory: DirectoryProperty + + /** + * Specify a version of the tool is installed + */ + abstract val version: Property + + /** + * Specify a command to run the tool + */ + abstract val command: Property + + /** + * Produce full serializable cache-friendly entity without Gradle Provider API + */ + internal abstract fun produceEnv(providerFactory: ProviderFactory): Provider +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/AbstractSettings.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/AbstractSettings.kt index 2b5afef228776..627b4f0de39d9 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/AbstractSettings.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/AbstractSettings.kt @@ -1,17 +1,56 @@ package org.jetbrains.kotlin.gradle.targets.js +import org.gradle.api.file.DirectoryProperty import org.jetbrains.kotlin.gradle.internal.ConfigurationPhaseAware +import org.jetbrains.kotlin.gradle.utils.getFile import java.io.File abstract class AbstractSettings : ConfigurationPhaseAware() { - abstract var download: Boolean + @Deprecated("This property has been migrated to support the Provider API. Use corresponding spec (extension with name *Spec) instead. This will be removed in version 2.2.") + var download: Boolean + get() = downloadProperty.get() + set(value) { + downloadProperty.set(value) + } - abstract var downloadBaseUrl: String? + internal abstract val downloadProperty: org.gradle.api.provider.Property - abstract var installationDir: File + // To prevent Kotlin build from failing (due to `-Werror`), only deprecate after upgrade of bootstrap version +// @Deprecated("This property has been migrated to support the Provider API. Use downloadBaseUrlProperty instead. This will be removed in version 2.2.") + var downloadBaseUrl: String? + get() = downloadBaseUrlProperty.getOrNull() + set(value) { + downloadBaseUrlProperty.set(value) + } - abstract var version: String + internal abstract val downloadBaseUrlProperty: org.gradle.api.provider.Property - abstract var command: String + @Deprecated("This property has been migrated to support the Provider API. Use corresponding spec (extension with name *Spec) instead. This will be removed in version 2.2.") + var installationDir: File + get() = installationDirectory.getFile() + set(value) { + installationDirectory.fileValue(value) + } + + internal abstract val installationDirectory: DirectoryProperty + + // To prevent Kotlin build from failing (due to `-Werror`), only deprecate after upgrade of bootstrap version +// @Deprecated("This property has been migrated to support the Provider API. Use corresponding spec (extension with name *Spec) instead. This will be removed in version 2.2.") + var version: String + get() = versionProperty.get() + set(value) { + versionProperty.set(value) + } + + internal abstract val versionProperty: org.gradle.api.provider.Property + + @Deprecated("This property has been migrated to support the Provider API. Use corresponding spec (extension with name *Spec) instead. This will be removed in version 2.2.") + var command: String + get() = commandProperty.get() + set(value) { + commandProperty.set(value) + } + + internal abstract val commandProperty: org.gradle.api.provider.Property } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/AbstractSetupTask.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/AbstractSetupTask.kt index d7abca1026f87..d01f086068c86 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/AbstractSetupTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/AbstractSetupTask.kt @@ -4,6 +4,7 @@ import org.gradle.api.DefaultTask import org.gradle.api.artifacts.Configuration import org.gradle.api.file.ArchiveOperations import org.gradle.api.file.FileSystemOperations +import org.gradle.api.file.RegularFileProperty import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.Provider import org.gradle.api.tasks.* @@ -12,14 +13,16 @@ import org.gradle.work.DisableCachingByDefault import org.jetbrains.kotlin.gradle.logging.kotlinInfo import org.jetbrains.kotlin.gradle.plugin.statistics.UrlRepoConfigurationMetrics import org.jetbrains.kotlin.gradle.plugin.statistics.UsesBuildFusService +import org.jetbrains.kotlin.gradle.utils.getFile +import org.jetbrains.kotlin.gradle.utils.mapOrNull import java.io.File import java.net.URI import javax.inject.Inject @DisableCachingByDefault -abstract class AbstractSetupTask> : DefaultTask(), UsesBuildFusService { - @get:Internal - protected abstract val settings: Settings +abstract class AbstractSetupTask>( + spec: Spec, +) : DefaultTask(), UsesBuildFusService { @get:Internal protected abstract val artifactPattern: String @@ -31,11 +34,9 @@ abstract class AbstractSetupTask = spec.produceEnv(project.providers) - private val shouldDownload by lazy { - env.download - } + private val shouldDownload: Provider = env.map { it.download } @get:Inject internal abstract val archiveOperations: ArchiveOperations @@ -49,19 +50,44 @@ abstract class AbstractSetupTask = env.map { it.ivyDependency } + + @Deprecated("Use ivyDependencyProvider instead. It uses Gradle Provider API.") val ivyDependency: String - @Input get() = env.ivyDependency + @Internal get() = ivyDependencyProvider.get() + @get:Input + @get:Optional + val downloadBaseUrlProvider: Provider = env.mapOrNull(project.providers) { + it.downloadBaseUrl + } + + @Deprecated("Use downloadBaseUrlProvider instead. It uses Gradle Provider API.") val downloadBaseUrl: String? - @Input - @Optional - get() = env.downloadBaseUrl + @Internal + get() = downloadBaseUrlProvider.orNull + + @get:OutputDirectory + internal val destinationProvider: RegularFileProperty = project.objects.fileProperty() + .fileProvider(env.map { it.dir }) + @Deprecated("Use destinationProvider instead. It uses Gradle Provider API.") val destination: File - @OutputDirectory get() = env.dir + @Internal get() = destinationProvider.getFile() + + @get:OutputFile + val destinationHashFileProvider: RegularFileProperty = project.objects.fileProperty() + .fileProvider( + destinationProvider.locationOnly.map { + val file = it.asFile + file.parentFile.resolve("${file.name}.hash") + } + ) + @Deprecated("Use destinationHashFileProvider instead. It uses Gradle Provider API.") val destinationHashFile: File - @OutputFile get() = destination.parentFile.resolve("${destination.name}.hash") + @Internal get() = destinationHashFileProvider.getFile() @Transient @get:Internal @@ -70,7 +96,7 @@ abstract class AbstractSetupTask withUrlRepo(action: () -> T): T { - val repo = downloadBaseUrl?.let { + val repo = downloadBaseUrlProvider.orNull?.let { project.repositories.ivy { repo -> repo.name = "Distributions at ${it}" repo.url = URI(it) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenExec.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenExec.kt index 9c821423a62c5..f01eb0ebe32aa 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenExec.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenExec.kt @@ -14,6 +14,7 @@ import org.gradle.api.provider.Provider import org.gradle.api.tasks.* import org.gradle.work.DisableCachingByDefault import org.gradle.work.NormalizeLineEndings +import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrCompilation import org.jetbrains.kotlin.gradle.tasks.registerTask import org.jetbrains.kotlin.gradle.utils.newFileProperty @@ -65,6 +66,7 @@ constructor() : AbstractExecTask(BinaryenExec::class.java) { } companion object { + @ExperimentalWasmDsl fun create( compilation: KotlinJsIrCompilation, name: String, diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenRootEnvSpec.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenRootEnvSpec.kt new file mode 100644 index 0000000000000..8125c198b1e74 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenRootEnvSpec.kt @@ -0,0 +1,64 @@ +/* + * Copyright 2010-2020 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.gradle.targets.js.binaryen + +import org.gradle.api.provider.Property +import org.gradle.api.provider.Provider +import org.gradle.api.provider.ProviderFactory +import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl +import org.jetbrains.kotlin.gradle.targets.js.EnvSpec +import org.jetbrains.kotlin.gradle.tasks.internal.CleanableStore +import org.jetbrains.kotlin.gradle.utils.getFile + +/** + * Specification for executing Binaryen, an optimization tool for wasm files. + */ +@ExperimentalWasmDsl +abstract class BinaryenRootEnvSpec : EnvSpec() { + + /** + * Specify Binaryen platform information, with name and architecture. + */ + internal abstract val platform: Property + + override fun produceEnv(providerFactory: ProviderFactory): Provider { + return providerFactory.provider { + val versionValue = version.get() + val requiredVersionName = "binaryen-version_$versionValue" + val cleanableStore = CleanableStore[installationDirectory.getFile().absolutePath] + val targetPath = cleanableStore[requiredVersionName].use() + val platformValue = platform.get() + val isWindows = platformValue.isWindows() + + val downloadValue = download.get() + fun getExecutable(command: String, customCommand: String, windowsExtension: String): String { + val finalCommand = + if (isWindows && customCommand == command) "$command.$windowsExtension" else customCommand + return if (downloadValue) + targetPath + .resolve("bin") + .resolve(finalCommand) + .absolutePath + else + finalCommand + } + + BinaryenEnv( + download = downloadValue, + downloadBaseUrl = downloadBaseUrl.orNull, + ivyDependency = "com.github.webassembly:binaryen:$versionValue:${platformValue.platform}@tar.gz", + executable = getExecutable("wasm-opt", command.get(), "exe"), + dir = targetPath, + cleanableStore = cleanableStore, + isWindows = isWindows, + ) + } + } + + companion object { + const val EXTENSION_NAME: String = "kotlinBinaryenSpec" + } +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenRootExtension.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenRootExtension.kt index 2b9a9b8180439..2f5528dd44172 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenRootExtension.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenRootExtension.kt @@ -6,14 +6,17 @@ package org.jetbrains.kotlin.gradle.targets.js.binaryen import org.gradle.api.Project +import org.gradle.api.file.DirectoryProperty import org.gradle.api.tasks.TaskProvider +import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl import org.jetbrains.kotlin.gradle.logging.kotlinInfo import org.jetbrains.kotlin.gradle.targets.js.AbstractSettings -import org.jetbrains.kotlin.gradle.tasks.internal.CleanableStore import org.jetbrains.kotlin.gradle.utils.property +@OptIn(ExperimentalWasmDsl::class) open class BinaryenRootExtension( - @Transient val rootProject: Project + @Transient val rootProject: Project, + private val binaryenSpec: BinaryenRootEnvSpec, ) : AbstractSettings() { init { check(rootProject.rootProject == rootProject) @@ -23,11 +26,21 @@ open class BinaryenRootExtension( rootProject.logger.kotlinInfo("Storing cached files in $it") } - override var installationDir by Property(gradleHome.resolve("binaryen")) - override var downloadBaseUrl: String? by Property("https://github.com/WebAssembly/binaryen/releases/download") - override var version: String by Property("118") - override var download: Boolean by Property(true) - override var command: String by Property("wasm-opt") + override val installationDirectory: DirectoryProperty = rootProject.objects.directoryProperty() + .fileValue(gradleHome.resolve("binaryen")) + + // value not convention because this property can be nullable to not add repository + override val downloadBaseUrlProperty: org.gradle.api.provider.Property = rootProject.objects.property() + .value("https://github.com/WebAssembly/binaryen/releases/download") + + override val versionProperty: org.gradle.api.provider.Property = rootProject.objects.property() + .convention("118") + + override val downloadProperty: org.gradle.api.provider.Property = rootProject.objects.property() + .convention(true) + + override val commandProperty: org.gradle.api.provider.Property = rootProject.objects.property() + .convention("wasm-opt") val setupTaskProvider: TaskProvider get() = rootProject.tasks.withType(BinaryenSetupTask::class.java).named(BinaryenSetupTask.NAME) @@ -35,32 +48,7 @@ open class BinaryenRootExtension( internal val platform: org.gradle.api.provider.Property = rootProject.objects.property() override fun finalizeConfiguration(): BinaryenEnv { - val platform = platform.get() - val requiredVersionName = "binaryen-version_$version" - val cleanableStore = CleanableStore[installationDir.absolutePath] - val targetPath = cleanableStore[requiredVersionName].use() - val isWindows = platform.isWindows() - - fun getExecutable(command: String, customCommand: String, windowsExtension: String): String { - val finalCommand = if (isWindows && customCommand == command) "$command.$windowsExtension" else customCommand - return if (download) - targetPath - .resolve("bin") - .resolve(finalCommand) - .absolutePath - else - finalCommand - } - - return BinaryenEnv( - download = download, - downloadBaseUrl = downloadBaseUrl, - ivyDependency = "com.github.webassembly:binaryen:$version:${platform.platform}@tar.gz", - executable = getExecutable("wasm-opt", command, "exe"), - dir = targetPath, - cleanableStore = cleanableStore, - isWindows = isWindows, - ) + return binaryenSpec.produceEnv(rootProject.providers).get() } companion object { diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenRootPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenRootPlugin.kt index 5749a5b07e319..258be91a90b03 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenRootPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenRootPlugin.kt @@ -8,6 +8,8 @@ package org.jetbrains.kotlin.gradle.targets.js.binaryen import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.plugins.BasePlugin +import org.gradle.api.plugins.ExtensionContainer +import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl import org.jetbrains.kotlin.gradle.internal.unameExecResult import org.jetbrains.kotlin.gradle.targets.js.MultiplePluginDeclarationDetector import org.jetbrains.kotlin.gradle.targets.js.binaryen.BinaryenPlatform.Companion.parseBinaryenPlatform @@ -17,6 +19,7 @@ import org.jetbrains.kotlin.gradle.tasks.registerTask import org.jetbrains.kotlin.gradle.utils.castIsolatedKotlinPluginClassLoaderAware import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly +@OptIn(ExperimentalWasmDsl::class) open class BinaryenRootPlugin : Plugin { override fun apply(project: Project) { MultiplePluginDeclarationDetector.detect(project) @@ -27,15 +30,24 @@ open class BinaryenRootPlugin : Plugin { "BinaryenRootPlugin can be applied only to root project" } - val settings = project.extensions.create(EXTENSION_NAME, BinaryenRootExtension::class.java, project) + val spec = project.extensions.createBinaryenRootEnvSpec() + + val settings = project.extensions.create( + EXTENSION_NAME, + BinaryenRootExtension::class.java, + project, + spec + ) + + spec.initializeBinaryenRootEnvSpec(settings) addPlatform(project, settings) - project.registerTask(BinaryenSetupTask.NAME) { + project.registerTask(BinaryenSetupTask.NAME, listOf(spec)) { it.group = TASKS_GROUP_NAME it.description = "Download and install a binaryen" - it.configuration = project.provider { - project.configurations.detachedConfiguration(project.dependencies.create(it.ivyDependency)) + it.configuration = it.ivyDependencyProvider.map { ivyDependency -> + project.configurations.detachedConfiguration(project.dependencies.create(ivyDependency)) .also { conf -> conf.isTransitive = false } } } @@ -47,6 +59,24 @@ open class BinaryenRootPlugin : Plugin { } } + private fun ExtensionContainer.createBinaryenRootEnvSpec(): BinaryenRootEnvSpec { + return create( + BinaryenRootEnvSpec.EXTENSION_NAME, + BinaryenRootEnvSpec::class.java + ) + } + + private fun BinaryenRootEnvSpec.initializeBinaryenRootEnvSpec( + rootBinaryen: BinaryenRootExtension, + ) { + download.convention(rootBinaryen.downloadProperty) + downloadBaseUrl.convention(rootBinaryen.downloadBaseUrlProperty) + installationDirectory.convention(rootBinaryen.installationDirectory) + version.convention(rootBinaryen.versionProperty) + command.convention(rootBinaryen.commandProperty) + platform.convention(rootBinaryen.platform) + } + private fun addPlatform(project: Project, extension: BinaryenRootExtension) { val uname = project.providers.unameExecResult diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenSetupTask.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenSetupTask.kt index 298c55da8154a..a88726ecc352f 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenSetupTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenSetupTask.kt @@ -7,15 +7,21 @@ package org.jetbrains.kotlin.gradle.targets.js.binaryen import org.gradle.api.tasks.Internal import org.gradle.work.DisableCachingByDefault +import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl +import org.jetbrains.kotlin.gradle.InternalKotlinGradlePluginApi import org.jetbrains.kotlin.gradle.targets.js.AbstractSetupTask -import org.jetbrains.kotlin.gradle.targets.js.binaryen.BinaryenRootPlugin.Companion.kotlinBinaryenExtension +import org.jetbrains.kotlin.gradle.utils.getFile import java.io.File +import javax.inject.Inject +@OptIn(ExperimentalWasmDsl::class) @DisableCachingByDefault -abstract class BinaryenSetupTask : AbstractSetupTask() { - @Transient - @Internal - override val settings = project.kotlinBinaryenExtension +abstract class BinaryenSetupTask +@Inject +@InternalKotlinGradlePluginApi +constructor( + settings: BinaryenRootEnvSpec, +) : AbstractSetupTask(settings) { @get:Internal override val artifactPattern: String @@ -29,14 +35,18 @@ abstract class BinaryenSetupTask : AbstractSetupTask() { + + // Latest version number could be found here https://storage.googleapis.com/chromium-v8/official/canary/v8-linux64-rel-latest.json + // Bash script/command to check that version specified in `VER` is available for all platforms, just copy-paste and run it in terminal: + /* + VER=${"$(curl -s https://storage.googleapis.com/chromium-v8/official/canary/v8-linux64-rel-latest.json)":13:-2} + echo "VER = $VER" + echo "==================" + for p in "mac64" "mac-arm64" "linux32" "linux64" "win32" "win64"; do + r=$(curl -I -s -o /dev/null -w "%{http_code}" https://storage.googleapis.com/chromium-v8/official/canary/v8-$p-rel-$VER.zip) + if [ "$r" -eq 200 ]; then + echo "$p \t✅"; + else + echo "$p \t❌"; + fi; + done; + */ + abstract override val version: org.gradle.api.provider.Property + + /** + * Specify the edition of the D8. + * + * Valid options for bundled version are `rel` (release variant) and `dbg` (debug variant). + */ + abstract val edition: org.gradle.api.provider.Property + + override fun produceEnv(providerFactory: ProviderFactory): Provider { + return providerFactory.provider { + val requiredVersion = "${D8Platform.platform}-${edition.get()}-${version.get()}" + val requiredVersionName = "v8-$requiredVersion" + val cleanableStore = CleanableStore[installationDirectory.getFile().absolutePath] + val targetPath = cleanableStore[requiredVersionName].use() + val isWindows = D8Platform.name == D8Platform.WIN + + val downloadValue = download.get() + fun getExecutable(command: String, customCommand: String, windowsExtension: String): String { + val finalCommand = + if (isWindows && customCommand == command) "$command.$windowsExtension" else customCommand + return if (downloadValue) + targetPath + .resolve(finalCommand) + .absolutePath + else + finalCommand + } + + D8Env( + download = downloadValue, + downloadBaseUrl = downloadBaseUrl.orNull, + ivyDependency = "google.d8:v8:$requiredVersion@zip", + executable = getExecutable("d8", command.get(), "exe"), + dir = targetPath, + cleanableStore = cleanableStore, + isWindows = isWindows, + ) + } + } + + companion object { + const val EXTENSION_NAME: String = "kotlinD8Spec" + } +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/d8/D8Exec.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/d8/D8Exec.kt index e9ca3218cac06..438fdf1b4b2ee 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/d8/D8Exec.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/d8/D8Exec.kt @@ -9,10 +9,12 @@ import org.gradle.api.file.RegularFileProperty import org.gradle.api.tasks.* import org.gradle.work.DisableCachingByDefault import org.gradle.work.NormalizeLineEndings +import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrCompilation import org.jetbrains.kotlin.gradle.tasks.registerTask import org.jetbrains.kotlin.gradle.utils.newFileProperty +@ExperimentalWasmDsl @DisableCachingByDefault open class D8Exec : AbstractExecTask(D8Exec::class.java) { init { @@ -57,11 +59,11 @@ open class D8Exec : AbstractExecTask(D8Exec::class.java) { ): TaskProvider { val target = compilation.target val project = target.project - val d8 = D8RootPlugin.apply(project.rootProject) + val d8 = D8Plugin.apply(project) return project.registerTask( name ) { - it.executable = d8.requireConfigured().executable + it.executable = d8.d8EnvSpec.produceEnv(project.providers).get().executable it.dependsOn(d8.setupTaskProvider) it.dependsOn(compilation.compileTaskProvider) it.configuration() diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/d8/D8Extension.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/d8/D8Extension.kt new file mode 100644 index 0000000000000..f9fbd2578c193 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/d8/D8Extension.kt @@ -0,0 +1,63 @@ +/* + * Copyright 2010-2020 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.gradle.targets.js.d8 + +import org.gradle.api.Project +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.tasks.TaskProvider +import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl +import org.jetbrains.kotlin.gradle.logging.kotlinInfo +import org.jetbrains.kotlin.gradle.targets.js.AbstractSettings +import org.jetbrains.kotlin.gradle.utils.property + +@OptIn(ExperimentalWasmDsl::class) +open class D8Extension( + @Transient val project: Project, + internal val d8EnvSpec: D8EnvSpec, +) : AbstractSettings() { + + private val gradleHome = project.gradle.gradleUserHomeDir.also { + project.logger.kotlinInfo("Storing cached files in $it") + } + + override val downloadProperty: org.gradle.api.provider.Property = project.objects.property() + .convention(true) + + // value not convention because this property can be nullable to not add repository + override val downloadBaseUrlProperty: org.gradle.api.provider.Property = project.objects.property() + .value("https://storage.googleapis.com/chromium-v8/official/canary") + + override val installationDirectory: DirectoryProperty = project.objects.directoryProperty() + .fileValue(gradleHome.resolve("d8")) + + /** + * The same as in [D8EnvSpec.version] + */ + override val versionProperty: org.gradle.api.provider.Property = project.objects.property() + .convention("11.9.85") + + /** + * Specify the edition of the D8. + * + * Valid options for bundled version are `rel` (release variant) and `dbg` (debug variant). + */ + val edition: org.gradle.api.provider.Property = project.objects.property() + .convention("rel") + + override val commandProperty: org.gradle.api.provider.Property = project.objects.property() + .convention("d8") + + val setupTaskProvider: TaskProvider + get() = project.tasks.withType(D8SetupTask::class.java).named(D8SetupTask.NAME) + + override fun finalizeConfiguration(): D8Env { + return d8EnvSpec.produceEnv(project.providers).get() + } + + companion object { + const val EXTENSION_NAME: String = "kotlinD8" + } +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/d8/D8Plugin.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/d8/D8Plugin.kt new file mode 100644 index 0000000000000..139d047032e5a --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/d8/D8Plugin.kt @@ -0,0 +1,86 @@ +/* + * Copyright 2010-2020 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.gradle.targets.js.d8 + +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.plugins.BasePlugin +import org.gradle.api.plugins.ExtensionContainer +import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl +import org.jetbrains.kotlin.gradle.InternalKotlinGradlePluginApi +import org.jetbrains.kotlin.gradle.targets.js.MultiplePluginDeclarationDetector +import org.jetbrains.kotlin.gradle.targets.js.d8.D8Extension.Companion.EXTENSION_NAME +import org.jetbrains.kotlin.gradle.tasks.CleanDataTask +import org.jetbrains.kotlin.gradle.tasks.registerTask +import org.jetbrains.kotlin.gradle.utils.castIsolatedKotlinPluginClassLoaderAware + +@OptIn(ExperimentalWasmDsl::class) +open class D8Plugin : Plugin { + override fun apply(project: Project) { + MultiplePluginDeclarationDetector.detect(project) + + project.plugins.apply(BasePlugin::class.java) + + val spec = project.extensions.createD8EnvSpec() + + val settings = project.extensions.create( + EXTENSION_NAME, + D8Extension::class.java, + project, + spec + ) + + spec.initializeD8EnvSpec(settings) + + project.registerTask(D8SetupTask.NAME, listOf(spec)) { + it.group = TASKS_GROUP_NAME + it.description = "Download and install a D8" + it.configuration = it.ivyDependencyProvider.map { ivyDependency -> + project.configurations.detachedConfiguration(project.dependencies.create(ivyDependency)) + .also { conf -> conf.isTransitive = false } + } + } + + project.registerTask("d8" + CleanDataTask.NAME_SUFFIX) { + it.cleanableStoreProvider = spec.produceEnv(project.providers).map { it.cleanableStore } + it.group = TASKS_GROUP_NAME + it.description = "Clean unused local d8 version" + } + } + + private fun ExtensionContainer.createD8EnvSpec(): D8EnvSpec { + return create( + D8EnvSpec.EXTENSION_NAME, + D8EnvSpec::class.java + ) + } + + private fun D8EnvSpec.initializeD8EnvSpec( + d8: D8Extension, + ) { + download.convention(d8.downloadProperty) + downloadBaseUrl.convention(d8.downloadBaseUrlProperty) + installationDirectory.convention(d8.installationDirectory) + version.convention(d8.versionProperty) + edition.convention(d8.edition) + command.convention(d8.commandProperty) + } + + companion object { + const val TASKS_GROUP_NAME: String = "d8" + + // To prevent Kotlin build from failing (due to `-Werror`), only internalize after upgrade of bootstrap version +// @InternalKotlinGradlePluginApi + fun apply(project: Project): D8Extension { + project.plugins.apply(D8Plugin::class.java) + return project.extensions.getByName(EXTENSION_NAME) as D8Extension + } + + @InternalKotlinGradlePluginApi + val Project.kotlinD8Extension: D8Extension + get() = extensions.getByName(EXTENSION_NAME).castIsolatedKotlinPluginClassLoaderAware() + } +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/d8/D8RootExtension.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/d8/D8RootExtension.kt index b8662074bf466..f511d7928da01 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/d8/D8RootExtension.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/d8/D8RootExtension.kt @@ -1,79 +1,14 @@ /* - * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2024 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.gradle.targets.js.d8 -import org.gradle.api.Project -import org.gradle.api.tasks.TaskProvider -import org.jetbrains.kotlin.gradle.logging.kotlinInfo -import org.jetbrains.kotlin.gradle.targets.js.AbstractSettings -import org.jetbrains.kotlin.gradle.tasks.internal.CleanableStore +import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl -open class D8RootExtension(@Transient val rootProject: Project) : AbstractSettings() { - init { - check(rootProject.rootProject == rootProject) - } - - private val gradleHome = rootProject.gradle.gradleUserHomeDir.also { - rootProject.logger.kotlinInfo("Storing cached files in $it") - } - - override var download: Boolean by Property(true) - override var downloadBaseUrl: String? by Property("https://storage.googleapis.com/chromium-v8/official/canary") - override var installationDir by Property(gradleHome.resolve("d8")) - - // Latest version number could be found here https://storage.googleapis.com/chromium-v8/official/canary/v8-linux64-rel-latest.json - // Bash script/command to check that version specified in `VER` is available for all platforms, just copy-paste and run it in terminal: - /* - VER=${"$(curl -s https://storage.googleapis.com/chromium-v8/official/canary/v8-linux64-rel-latest.json)":13:-2} - echo "VER = $VER" - echo "==================" - for p in "mac64" "mac-arm64" "linux32" "linux64" "win32" "win64"; do - r=$(curl -I -s -o /dev/null -w "%{http_code}" https://storage.googleapis.com/chromium-v8/official/canary/v8-$p-rel-$VER.zip) - if [ "$r" -eq 200 ]; then - echo "$p \t✅"; - else - echo "$p \t❌"; - fi; - done; - */ - override var version by Property("11.9.85") - var edition by Property("rel") // rel or dbg - override var command by Property("d8") - - val setupTaskProvider: TaskProvider - get() = rootProject.tasks.withType(D8SetupTask::class.java).named(D8SetupTask.NAME) - - override fun finalizeConfiguration(): D8Env { - val requiredVersionName = "v8-${D8Platform.platform}-$edition-$version" - val cleanableStore = CleanableStore[installationDir.absolutePath] - val targetPath = cleanableStore[requiredVersionName].use() - val isWindows = D8Platform.name == D8Platform.WIN - - fun getExecutable(command: String, customCommand: String, windowsExtension: String): String { - val finalCommand = if (isWindows && customCommand == command) "$command.$windowsExtension" else customCommand - return if (download) - targetPath - .resolve(finalCommand) - .absolutePath - else - finalCommand - } - - return D8Env( - download = download, - downloadBaseUrl = downloadBaseUrl, - ivyDependency = "google.d8:v8:${D8Platform.platform}-$edition-$version@zip", - executable = getExecutable("d8", command, "exe"), - dir = targetPath, - cleanableStore = cleanableStore, - isWindows = isWindows, - ) - } - - companion object { - const val EXTENSION_NAME: String = "kotlinD8" - } -} +// To be compatible with previous KGP version, we need to keep D8RootExtension as deprecated. +// To prevent Kotlin build from failing (due to `-Werror`), only deprecate after upgrade of bootstrap version +//@Deprecated("This extension is deprecated. Use D8Extension instead.", ReplaceWith("D8Extension")) +@OptIn(ExperimentalWasmDsl::class) +typealias D8RootExtension = D8Extension \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/d8/D8RootPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/d8/D8RootPlugin.kt index efdcf9ae09c7c..fd0097c057d3e 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/d8/D8RootPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/d8/D8RootPlugin.kt @@ -1,58 +1,14 @@ /* - * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Copyright 2010-2024 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.gradle.targets.js.d8 -import org.gradle.api.Plugin -import org.gradle.api.Project -import org.gradle.api.plugins.BasePlugin -import org.jetbrains.kotlin.gradle.targets.js.MultiplePluginDeclarationDetector -import org.jetbrains.kotlin.gradle.targets.js.d8.D8RootExtension.Companion.EXTENSION_NAME -import org.jetbrains.kotlin.gradle.tasks.CleanDataTask -import org.jetbrains.kotlin.gradle.tasks.registerTask -import org.jetbrains.kotlin.gradle.utils.castIsolatedKotlinPluginClassLoaderAware +import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl - -open class D8RootPlugin : Plugin { - override fun apply(project: Project) { - MultiplePluginDeclarationDetector.detect(project) - - project.plugins.apply(BasePlugin::class.java) - - check(project == project.rootProject) { - "D8RootPlugin can be applied only to root project" - } - - val settings = project.extensions.create(EXTENSION_NAME, D8RootExtension::class.java, project) - - project.registerTask(D8SetupTask.NAME) { - it.group = TASKS_GROUP_NAME - it.description = "Download and install a D8" - it.configuration = project.provider { - project.configurations.detachedConfiguration(project.dependencies.create(it.ivyDependency)) - .also { conf -> conf.isTransitive = false } - } - } - - project.registerTask("d8" + CleanDataTask.NAME_SUFFIX) { - it.cleanableStoreProvider = project.provider { settings.requireConfigured().cleanableStore } - it.group = TASKS_GROUP_NAME - it.description = "Clean unused local d8 version" - } - } - - companion object { - const val TASKS_GROUP_NAME: String = "d8" - - fun apply(rootProject: Project): D8RootExtension { - check(rootProject == rootProject.rootProject) - rootProject.plugins.apply(D8RootPlugin::class.java) - return rootProject.extensions.getByName(EXTENSION_NAME) as D8RootExtension - } - - val Project.kotlinD8Extension: D8RootExtension - get() = extensions.getByName(EXTENSION_NAME).castIsolatedKotlinPluginClassLoaderAware() - } -} +// To be compatible with previous KGP version, we need to keep D8RootPlugin as deprecated. +// To prevent Kotlin build from failing (due to `-Werror`), only deprecate after upgrade of bootstrap version +//@Deprecated("This type is deprecated. Use D8Plugin instead.", ReplaceWith("D8Plugin")) +@OptIn(ExperimentalWasmDsl::class) +typealias D8RootPlugin = D8Plugin \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/d8/D8SetupTask.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/d8/D8SetupTask.kt index a1311b44f0c67..f1e0d37018dbf 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/d8/D8SetupTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/d8/D8SetupTask.kt @@ -3,19 +3,22 @@ * that can be found in the license/LICENSE.txt file. */ +@file:OptIn(ExperimentalWasmDsl::class) + package org.jetbrains.kotlin.gradle.targets.js.d8 import org.gradle.api.tasks.Internal import org.gradle.work.DisableCachingByDefault +import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl import org.jetbrains.kotlin.gradle.targets.js.AbstractSetupTask -import org.jetbrains.kotlin.gradle.targets.js.d8.D8RootPlugin.Companion.kotlinD8Extension +import org.jetbrains.kotlin.gradle.utils.getFile import java.io.File +import javax.inject.Inject @DisableCachingByDefault -abstract class D8SetupTask : AbstractSetupTask() { - @Transient - @Internal - override val settings = project.kotlinD8Extension +abstract class D8SetupTask @Inject constructor( + settings: D8EnvSpec, +) : AbstractSetupTask(settings) { @get:Internal override val artifactPattern: String @@ -29,14 +32,18 @@ abstract class D8SetupTask : AbstractSetupTask() { override val artifactName: String get() = "v8" + private val isWindows = env.map { it.isWindows } + + private val executable = env.map { it.executable } + override fun extract(archive: File) { fs.copy { it.from(archiveOperations.zipTree(archive)) - it.into(destination) + it.into(destinationProvider.getFile()) } - if (!env.isWindows) { - File(env.executable).setExecutable(true) + if (!isWindows.get()) { + File(executable.get()).setExecutable(true) } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/dsl/KotlinWasmJsTargetDsl.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/dsl/KotlinWasmJsTargetDsl.kt index 37cd9a628bade..49efbaffcf2f1 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/dsl/KotlinWasmJsTargetDsl.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/dsl/KotlinWasmJsTargetDsl.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.gradle.targets.js.dsl import org.gradle.api.Action +import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl import org.jetbrains.kotlin.gradle.plugin.KotlinTarget import org.jetbrains.kotlin.gradle.targets.js.binaryen.BinaryenExec import org.jetbrains.kotlin.gradle.targets.js.d8.D8Exec @@ -28,6 +29,7 @@ interface KotlinWasmJsTargetDsl : KotlinWasmTargetDsl, KotlinJsTargetDsl { } } +@OptIn(ExperimentalWasmDsl::class) interface KotlinWasmD8Dsl : KotlinJsSubTargetDsl { fun runTask(body: D8Exec.() -> Unit) } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/JsBinaries.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/JsBinaries.kt index 017393b8c2ec1..56a09320f279e 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/JsBinaries.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/JsBinaries.kt @@ -12,6 +12,7 @@ import org.gradle.api.file.RegularFile import org.gradle.api.provider.Provider import org.gradle.api.tasks.TaskProvider import org.gradle.language.base.plugins.LifecycleBasePlugin +import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl import org.jetbrains.kotlin.gradle.dsl.KotlinJsCompilerOptionsHelper import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation @@ -188,6 +189,7 @@ open class Executable( ) } +@OptIn(ExperimentalWasmDsl::class) open class ExecutableWasm( compilation: KotlinJsIrCompilation, name: String, diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinBrowserJsIr.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinBrowserJsIr.kt index 4af93e32cb6fa..62022fff8aa47 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinBrowserJsIr.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinBrowserJsIr.kt @@ -21,8 +21,9 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.isMain import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalDceDsl import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsBinaryMode import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsBrowserDsl +import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsPlugin.Companion.kotlinNodeJsEnvSpec import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension -import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension +import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsRootExtension import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest import org.jetbrains.kotlin.gradle.targets.js.testing.karma.KotlinKarma @@ -43,7 +44,8 @@ abstract class KotlinBrowserJsIr @Inject constructor(target: KotlinJsIrTarget) : KotlinJsIrSubTarget(target, "browser"), KotlinJsBrowserDsl { - private val nodeJs = project.rootProject.kotlinNodeJsExtension + private val nodeJsRoot = project.rootProject.kotlinNodeJsRootExtension + private val nodeJs = project.kotlinNodeJsEnvSpec private val webpackTaskConfigurations = project.objects.domainObjectSet>() private val runTaskConfigurations = project.objects.domainObjectSet>() @@ -53,10 +55,12 @@ abstract class KotlinBrowserJsIr @Inject constructor(target: KotlinJsIrTarget) : override fun configureTestDependencies(test: KotlinJsTest) { test.dependsOn( - nodeJs.npmInstallTaskProvider, - nodeJs.nodeJsSetupTaskProvider + nodeJsRoot.npmInstallTaskProvider, ) - test.dependsOn(nodeJs.packageManagerExtension.map { it.postInstallTasks }) + with(nodeJs) { + test.dependsOn(project.nodeJsSetupTaskProvider) + } + test.dependsOn(nodeJsRoot.packageManagerExtension.map { it.postInstallTasks }) } override fun configureDefaultTestFramework(test: KotlinJsTest) { @@ -67,7 +71,7 @@ abstract class KotlinBrowserJsIr @Inject constructor(target: KotlinJsIrTarget) : } if (test.enabled) { - nodeJs.taskRequirements.addTaskRequirements(test) + nodeJsRoot.taskRequirements.addTaskRequirements(test) } } @@ -165,7 +169,7 @@ abstract class KotlinBrowserJsIr @Inject constructor(target: KotlinJsIrTarget) : ), entryModuleName = binary.linkTask.flatMap { it.compilerOptions.moduleName }, configurationActions = runTaskConfigurations, - nodeJs = nodeJs, + nodeJs = nodeJsRoot, defaultArchivesName = archivesName, ) } @@ -220,7 +224,7 @@ abstract class KotlinBrowserJsIr @Inject constructor(target: KotlinJsIrTarget) : ), entryModuleName = binary.linkTask.flatMap { it.compilerOptions.moduleName }, configurationActions = webpackTaskConfigurations, - nodeJs = nodeJs, + nodeJs = nodeJsRoot, defaultArchivesName = archivesName, ) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinD8Ir.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinD8Ir.kt index 648f6fab80dfa..2cc7a1a4206f0 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinD8Ir.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinD8Ir.kt @@ -5,8 +5,9 @@ package org.jetbrains.kotlin.gradle.targets.js.ir +import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl import org.jetbrains.kotlin.gradle.targets.js.d8.D8Exec -import org.jetbrains.kotlin.gradle.targets.js.d8.D8RootPlugin +import org.jetbrains.kotlin.gradle.targets.js.d8.D8Plugin import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinWasmD8Dsl import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinWasmD8 @@ -15,11 +16,12 @@ import org.jetbrains.kotlin.gradle.tasks.locateTask import org.jetbrains.kotlin.gradle.tasks.withType import javax.inject.Inject +@OptIn(ExperimentalWasmDsl::class) abstract class KotlinD8Ir @Inject constructor(target: KotlinJsIrTarget) : KotlinJsIrSubTargetBase(target, "d8"), KotlinWasmD8Dsl { - private val d8 = D8RootPlugin.apply(project.rootProject) + private val d8 = D8Plugin.apply(project) override val testTaskDescription: String get() = "Run all ${target.name} tests inside d8 using the builtin test framework" diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrTarget.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrTarget.kt index 96cc4b6166427..a4badad5633e4 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrTarget.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsIrTarget.kt @@ -8,9 +8,7 @@ package org.jetbrains.kotlin.gradle.targets.js.ir import org.gradle.api.NamedDomainObjectContainer import org.gradle.api.Project import org.gradle.api.Task -import org.gradle.api.file.DuplicatesStrategy import org.gradle.api.tasks.TaskProvider -import org.gradle.language.jvm.tasks.ProcessResources import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi import org.jetbrains.kotlin.gradle.dsl.* import org.jetbrains.kotlin.gradle.plugin.AbstractKotlinTargetConfigurator.Companion.runTaskNameSuffix @@ -20,7 +18,6 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType import org.jetbrains.kotlin.gradle.plugin.KotlinTargetComponent import org.jetbrains.kotlin.gradle.plugin.KotlinTargetWithTests import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider -import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider import org.jetbrains.kotlin.gradle.plugin.mpp.* import org.jetbrains.kotlin.gradle.plugin.mpp.resources.publication.setUpResourcesVariant import org.jetbrains.kotlin.gradle.targets.js.JsAggregatingExecutionSource @@ -30,6 +27,7 @@ import org.jetbrains.kotlin.gradle.targets.js.KotlinWasmTargetType import org.jetbrains.kotlin.gradle.targets.js.binaryen.BinaryenExec import org.jetbrains.kotlin.gradle.targets.js.dsl.* import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTargetConfigurator.Companion.configureJsDefaultOptions +import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsPlugin import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin import org.jetbrains.kotlin.gradle.targets.js.npm.NpmResolverPlugin import org.jetbrains.kotlin.gradle.targets.js.typescript.TypeScriptValidationTask @@ -232,6 +230,7 @@ constructor( if (wasmTargetType != KotlinWasmTargetType.WASI) { commonLazy } else { + NodeJsPlugin.apply(project) NodeJsRootPlugin.apply(project.rootProject) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinNodeJsIr.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinNodeJsIr.kt index 7cc0d2c17461c..0495621625b43 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinNodeJsIr.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinNodeJsIr.kt @@ -12,7 +12,8 @@ import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalMainFunctionArgume import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsBinaryMode import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsNodeDsl import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsExec -import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension +import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsPlugin.Companion.kotlinNodeJsEnvSpec +import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsRootExtension import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinWasmNode import org.jetbrains.kotlin.gradle.tasks.dependsOn @@ -24,8 +25,7 @@ abstract class KotlinNodeJsIr @Inject constructor(target: KotlinJsIrTarget) : KotlinJsIrSubTargetBase(target, "node"), KotlinJsNodeDsl { - private val nodeJs = project.rootProject.kotlinNodeJsExtension - private val nodeJsTaskProviders = project.rootProject.kotlinNodeJsExtension + private val nodeJs = project.kotlinNodeJsEnvSpec override val testTaskDescription: String get() = "Run all ${target.name} tests inside nodejs using the builtin test framework" @@ -66,22 +66,26 @@ abstract class KotlinNodeJsIr @Inject constructor(target: KotlinJsIrTarget) : } override fun configureTestDependencies(test: KotlinJsTest) { - test.dependsOn(nodeJsTaskProviders.nodeJsSetupTaskProvider) + with(nodeJs) { + test.dependsOn(project.nodeJsSetupTaskProvider) + } if (target.wasmTargetType != KotlinWasmTargetType.WASI) { + val nodeJsRoot = project.rootProject.kotlinNodeJsRootExtension test.dependsOn( - nodeJsTaskProviders.npmInstallTaskProvider, + nodeJsRoot.npmInstallTaskProvider, ) - test.dependsOn(nodeJs.packageManagerExtension.map { it.postInstallTasks }) + test.dependsOn(nodeJsRoot.packageManagerExtension.map { it.postInstallTasks }) } } override fun configureDefaultTestFramework(test: KotlinJsTest) { if (target.platformType != KotlinPlatformType.wasm) { + val nodeJsRoot = project.rootProject.kotlinNodeJsRootExtension if (test.testFramework == null) { test.useMocha { } } if (test.enabled) { - nodeJs.taskRequirements.addTaskRequirements(test) + nodeJsRoot.taskRequirements.addTaskRequirements(test) } } else { test.testFramework = KotlinWasmNode(test) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsEnv.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsEnv.kt index 0574e560c8112..3f3859baaf618 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsEnv.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsEnv.kt @@ -8,7 +8,6 @@ import java.io.File data class NodeJsEnv( override val download: Boolean, override val cleanableStore: CleanableStore, - val rootPackageDir: File, override val dir: File, val nodeBinDir: File, override val executable: String, @@ -16,8 +15,6 @@ data class NodeJsEnv( val architectureName: String, override val ivyDependency: String, override val downloadBaseUrl: String?, - - val packageManager: NpmApiExecution, ) : AbstractEnv { val isWindows: Boolean get() = platformName == "win" diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsEnvSpec.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsEnvSpec.kt new file mode 100644 index 0000000000000..d14e2bde6406b --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsEnvSpec.kt @@ -0,0 +1,72 @@ +/* + * Copyright 2010-2020 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.gradle.targets.js.nodejs + +import org.gradle.api.Project +import org.gradle.api.provider.Provider +import org.gradle.api.provider.ProviderFactory +import org.gradle.api.tasks.TaskProvider +import org.jetbrains.kotlin.gradle.targets.js.EnvSpec +import org.jetbrains.kotlin.gradle.tasks.internal.CleanableStore +import org.jetbrains.kotlin.gradle.utils.getFile +import java.io.File + +/** + * Spec for Node.js - common JS and Wasm runtime. + */ +abstract class NodeJsEnvSpec : EnvSpec() { + + /** + * Specify a platform information with name and architecture + */ + internal abstract val platform: org.gradle.api.provider.Property + + override fun produceEnv(providerFactory: ProviderFactory): Provider { + return providerFactory.provider { + val platformValue = platform.get() + val name = platformValue.name + val architecture = platformValue.arch + + val versionValue = version.get() + val nodeDirName = "node-v$versionValue-$name-$architecture" + val cleanableStore = CleanableStore[installationDirectory.getFile().absolutePath] + val nodeDir = cleanableStore[nodeDirName].use() + val isWindows = platformValue.isWindows() + val nodeBinDir = if (isWindows) nodeDir else nodeDir.resolve("bin") + + val downloadValue = download.get() + fun getExecutable(command: String, customCommand: String, windowsExtension: String): String { + val finalCommand = + if (isWindows && customCommand == command) "$command.$windowsExtension" else customCommand + return if (downloadValue) File(nodeBinDir, finalCommand).absolutePath else finalCommand + } + + fun getIvyDependency(): String { + val type = if (isWindows) "zip" else "tar.gz" + return "org.nodejs:node:$versionValue:$name-$architecture@$type" + } + + NodeJsEnv( + download = downloadValue, + cleanableStore = cleanableStore, + dir = nodeDir, + nodeBinDir = nodeBinDir, + executable = getExecutable("node", command.get(), "exe"), + platformName = name, + architectureName = architecture, + ivyDependency = getIvyDependency(), + downloadBaseUrl = downloadBaseUrl.orNull, + ) + } + } + + val Project.nodeJsSetupTaskProvider: TaskProvider + get() = project.tasks.withType(NodeJsSetupTask::class.java).named(NodeJsSetupTask.NAME) + + companion object { + const val EXTENSION_NAME: String = "kotlinNodeJsSpec" + } +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsExec.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsExec.kt index ac0c20ddaa226..4f8940818cda1 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsExec.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsExec.kt @@ -14,7 +14,7 @@ import org.jetbrains.kotlin.gradle.targets.js.KotlinWasmTargetType import org.jetbrains.kotlin.gradle.targets.js.RequiredKotlinJsDependency import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrCompilation import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTarget -import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension +import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsRootExtension import org.jetbrains.kotlin.gradle.targets.js.npm.RequiresNpmDependencies import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject import org.jetbrains.kotlin.gradle.tasks.registerTask @@ -31,7 +31,7 @@ constructor( ) : AbstractExecTask(NodeJsExec::class.java), RequiresNpmDependencies { @Transient @get:Internal - lateinit var nodeJs: NodeJsRootExtension + lateinit var nodeJsRoot: NodeJsRootExtension @Internal val npmProject = compilation.npmProject @@ -60,7 +60,7 @@ constructor( override val requiredNpmDependencies: Set by lazy { mutableSetOf().also { if (sourceMapStackTraces) { - it.add(nodeJs.versions.sourceMapSupport) + it.add(nodeJsRoot.versions.sourceMapSupport) } } } @@ -96,25 +96,27 @@ constructor( ): TaskProvider { val target = compilation.target val project = target.project - NodeJsRootPlugin.apply(project.rootProject) - val nodeJs = project.rootProject.kotlinNodeJsExtension - val nodeJsTaskProviders = project.rootProject.kotlinNodeJsExtension + val nodeJsRoot = NodeJsRootPlugin.apply(project.rootProject) + val nodeJs = NodeJsPlugin.apply(project) + val nodeJsTaskProviders = project.rootProject.kotlinNodeJsRootExtension val npmProject = compilation.npmProject return project.registerTask( name, listOf(compilation) ) { - it.nodeJs = nodeJs - it.executable = nodeJs.requireConfigured().executable + it.nodeJsRoot = nodeJsRoot + it.executable = nodeJs.produceEnv(project.providers).get().executable if ((compilation.target as? KotlinJsIrTarget)?.wasmTargetType != KotlinWasmTargetType.WASI) { it.workingDir(npmProject.dir) it.dependsOn( nodeJsTaskProviders.npmInstallTaskProvider, ) - it.dependsOn(nodeJs.packageManagerExtension.map { it.postInstallTasks }) + it.dependsOn(nodeJsRoot.packageManagerExtension.map { it.postInstallTasks }) + } + with(nodeJs) { + it.dependsOn(project.nodeJsSetupTaskProvider) } - it.dependsOn(nodeJsTaskProviders.nodeJsSetupTaskProvider) it.dependsOn(compilation.compileTaskProvider) it.configuration() } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsPlugin.kt new file mode 100644 index 0000000000000..43349bd84fe75 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsPlugin.kt @@ -0,0 +1,86 @@ +/* + * Copyright 2010-2020 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.gradle.targets.js.nodejs + +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.jetbrains.kotlin.gradle.internal.unameExecResult +import org.jetbrains.kotlin.gradle.targets.js.MultiplePluginDeclarationDetector +import org.jetbrains.kotlin.gradle.tasks.registerTask +import org.jetbrains.kotlin.gradle.utils.castIsolatedKotlinPluginClassLoaderAware +import org.jetbrains.kotlin.gradle.utils.providerWithLazyConvention + +open class NodeJsPlugin : Plugin { + override fun apply(project: Project) { + MultiplePluginDeclarationDetector.detect(project) + + val nodeJs = project.createNodeJsEnvSpec { + NodeJsRootPlugin.apply(project.rootProject) + } + + project.registerTask(NodeJsSetupTask.NAME, listOf(nodeJs)) { + it.group = TASKS_GROUP_NAME + it.description = "Download and install a local node/npm version" + it.configuration = it.ivyDependencyProvider.map { ivyDependency -> + project.configurations.detachedConfiguration(project.dependencies.create(ivyDependency)) + .also { conf -> conf.isTransitive = false } + } + } + } + + @Suppress("DEPRECATION") + private fun Project.createNodeJsEnvSpec( + nodeJsConstructor: () -> NodeJsRootExtension, + ): NodeJsEnvSpec { + val extensions = extensions + val objects = objects + + return extensions.create( + NodeJsEnvSpec.EXTENSION_NAME, + NodeJsEnvSpec::class.java + ).apply { + installationDirectory.convention( + objects.directoryProperty().fileProvider( + objects.providerWithLazyConvention { + nodeJsConstructor().installationDir + } + ) + ) + download.convention(objects.providerWithLazyConvention { nodeJsConstructor().download }) + downloadBaseUrl.convention(objects.providerWithLazyConvention { nodeJsConstructor().downloadBaseUrl }) + version.convention(objects.providerWithLazyConvention { nodeJsConstructor().version }) + command.convention(objects.providerWithLazyConvention { nodeJsConstructor().command }) + + addPlatform(this@createNodeJsEnvSpec, this) + } + } + + private fun addPlatform(project: Project, extension: NodeJsEnvSpec) { + val uname = project.providers + .unameExecResult + + extension.platform.value( + project.providers.systemProperty("os.name") + .zip( + project.providers.systemProperty("os.arch") + ) { name, arch -> + parsePlatform(name, arch, uname) + } + ).disallowChanges() + } + + companion object { + const val TASKS_GROUP_NAME: String = "nodeJs" + + fun apply(project: Project): NodeJsEnvSpec { + project.plugins.apply(NodeJsPlugin::class.java) + return project.extensions.getByName(NodeJsEnvSpec.EXTENSION_NAME) as NodeJsEnvSpec + } + + val Project.kotlinNodeJsEnvSpec: NodeJsEnvSpec + get() = extensions.getByName(NodeJsEnvSpec.EXTENSION_NAME).castIsolatedKotlinPluginClassLoaderAware() + } +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootExtension.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootExtension.kt index f3aa43855e543..65857b7c96214 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootExtension.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootExtension.kt @@ -12,23 +12,19 @@ import org.gradle.api.provider.Provider import org.gradle.api.tasks.TaskProvider import org.jetbrains.kotlin.gradle.logging.kotlinInfo import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider -import org.jetbrains.kotlin.gradle.targets.js.AbstractSettings import org.jetbrains.kotlin.gradle.targets.js.NpmVersions import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinRootNpmResolver import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.PACKAGE_JSON_UMBRELLA_TASK_NAME import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmCachesSetup import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmInstallTask import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.RootPackageJsonTask -import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnLockStoreTask -import org.jetbrains.kotlin.gradle.targets.js.yarn.yarn -import org.jetbrains.kotlin.gradle.tasks.internal.CleanableStore -import org.jetbrains.kotlin.gradle.utils.getFile import org.jetbrains.kotlin.gradle.utils.property import java.io.File open class NodeJsRootExtension( val project: Project, -) : AbstractSettings() { + private val nodeJs: () -> NodeJsEnvSpec, +) { init { check(project.rootProject == project) @@ -49,46 +45,63 @@ open class NodeJsRootExtension( } } - val rootProjectDir - get() = project.rootDir - private val gradleHome = project.gradle.gradleUserHomeDir.also { project.logger.kotlinInfo("Storing cached files in $it") } - override var installationDir by Property(gradleHome.resolve("nodejs")) + @Deprecated( + "Use installationDir from NodeJsExtension (not NodeJsRootExtension) instead." + + "You can find this extension after applying NodeJsPlugin. This will be removed in 2.2" + ) + var installationDir: File = gradleHome.resolve("nodejs") - override var download by Property(true) + @Deprecated( + "Use download from NodeJsExtension (not NodeJsRootExtension) instead" + + "You can find this extension after applying NodeJsPlugin. This will be removed in 2.2" + ) + var download = true - @Deprecated("Use downloadBaseUrl instead", ReplaceWith("downloadBaseUrl")) - var nodeDownloadBaseUrl - get() = downloadBaseUrl - set(value) { - downloadBaseUrl = value - } + @Deprecated( + "Use downloadBaseUrl from NodeJsExtension (not NodeJsRootExtension) instead" + + "You can find this extension after applying NodeJsPlugin. This will be removed in 2.2" + ) + var nodeDownloadBaseUrl by ::downloadBaseUrl - override var downloadBaseUrl: String? by Property("https://nodejs.org/dist") + // To prevent Kotlin build from failing (due to `-Werror`), only deprecate after upgrade of bootstrap version +// @Deprecated( +// "Use downloadBaseUrl from NodeJsExtension (not NodeJsRootExtension) instead" + +// "You can find this extension after applying NodeJsPlugin. This will be removed in 2.2" +// ) + var downloadBaseUrl: String? = "https://nodejs.org/dist" - @Deprecated("Use version instead", ReplaceWith("version")) - var nodeVersion - get() = version - set(value) { - version = value - } + @Deprecated( + "Use version from NodeJsExtension (not NodeJsRootExtension) instead" + + "You can find this extension after applying NodeJsPlugin. This will be removed in 2.2" + ) + var nodeVersion by ::version - // Release schedule: https://github.com/nodejs/Release - // Actual LTS and Current versions: https://nodejs.org/en/download/ - // Older versions and more information, e.g. V8 version inside: https://nodejs.org/en/download/releases/ - override var version by Property("22.0.0") + // To prevent Kotlin build from failing (due to `-Werror`), only deprecate after upgrade of bootstrap version +// @Deprecated( +// "Use downloadBaseUrl from NodeJsExtension (not NodeJsRootExtension) instead" + +// "You can find this extension after applying NodeJsPlugin. This will be removed in 2.2" +// ) + var version = "22.0.0" - override var command by Property("node") + @Deprecated( + "Use command from NodeJsExtension (not NodeJsRootExtension) instead" + + "You can find this extension after applying NodeJsPlugin. This will be removed in 2.2" + ) + var command = "node" - @Deprecated("Use command instead", ReplaceWith("command")) - var nodeCommand - get() = command - set(value) { - command = value - } + @Suppress("DEPRECATION") + @Deprecated( + "Use command from NodeJsExtension (not NodeJsRootExtension) instead" + + "You can find this extension after applying NodeJsPlugin. This will be removed in 2.2" + ) + var nodeCommand by ::command + + val rootProjectDir + get() = project.rootDir val packageManagerExtension: org.gradle.api.provider.Property = project.objects.property() @@ -99,77 +112,14 @@ open class NodeJsRootExtension( val rootPackageDirectory: Provider = project.layout.buildDirectory.dir("js") - @Deprecated( - "This property is deprecated and will be removed in future. Use rootPackageDirectory instead", - replaceWith = ReplaceWith("rootPackageDirectory") - ) - val rootPackageDir: File - get() = rootPackageDirectory.getFile() - val projectPackagesDirectory: Provider get() = rootPackageDirectory.map { it.dir("packages") } - @Deprecated( - "This property is deprecated and will be removed in future. Use projectPackagesDirectory instead", - replaceWith = ReplaceWith("projectPackagesDirectory") - ) - val projectPackagesDir: File - get() = projectPackagesDirectory.getFile() - val nodeModulesGradleCacheDirectory: Provider get() = rootPackageDirectory.map { it.dir("packages_imported") } - @Deprecated( - "This property is deprecated and will be removed in future. Use nodeModulesGradleCacheDirectory instead", - replaceWith = ReplaceWith("nodeModulesGradleCacheDirectory") - ) - val nodeModulesGradleCacheDir: File - get() = nodeModulesGradleCacheDirectory.getFile() - - internal val platform: org.gradle.api.provider.Property = project.objects.property() - val versions = NpmVersions() - override fun finalizeConfiguration(): NodeJsEnv { - val name = platform.get().name - val architecture = platform.get().arch - - val nodeDirName = "node-v$version-$name-$architecture" - val cleanableStore = CleanableStore[installationDir.absolutePath] - val nodeDir = cleanableStore[nodeDirName].use() - val isWindows = platform.get().isWindows() - val nodeBinDir = if (isWindows) nodeDir else nodeDir.resolve("bin") - - fun getExecutable(command: String, customCommand: String, windowsExtension: String): String { - val finalCommand = if (isWindows && customCommand == command) "$command.$windowsExtension" else customCommand - return if (download) File(nodeBinDir, finalCommand).absolutePath else finalCommand - } - - fun getIvyDependency(): String { - val type = if (isWindows) "zip" else "tar.gz" - return "org.nodejs:node:$version:$name-$architecture@$type" - } - - packageManagerExtension.disallowChanges() - - return NodeJsEnv( - download = download, - cleanableStore = cleanableStore, - rootPackageDir = rootPackageDirectory.getFile(), - dir = nodeDir, - nodeBinDir = nodeBinDir, - executable = getExecutable("node", command, "exe"), - platformName = name, - architectureName = architecture, - ivyDependency = getIvyDependency(), - downloadBaseUrl = downloadBaseUrl, - packageManager = packageManagerExtension.get().packageManager - ) - } - - val nodeJsSetupTaskProvider: TaskProvider - get() = project.tasks.withType(NodeJsSetupTask::class.java).named(NodeJsSetupTask.NAME) - val npmInstallTaskProvider: TaskProvider get() = project.tasks.withType(KotlinNpmInstallTask::class.java).named(KotlinNpmInstallTask.NAME) @@ -182,9 +132,19 @@ open class NodeJsRootExtension( val npmCachesSetupTaskProvider: TaskProvider get() = project.tasks.withType(KotlinNpmCachesSetup::class.java).named(KotlinNpmCachesSetup.NAME) - @Deprecated("This is deprecated and will be removed. Use corresponding property from YarnRootExtension") - val storeYarnLockTaskProvider: TaskProvider - get() = project.yarn.storeYarnLockTaskProvider + @Deprecated( + "Use nodeJsSetupTaskProvider from NodeJsExtension (not NodeJsRootExtension) instead" + + "You can find this extension after applying NodeJsPlugin" + ) + val nodeJsSetupTaskProvider: TaskProvider + get() = with(nodeJs()) { + project.nodeJsSetupTaskProvider + } + + @Deprecated("Use NodeJsExtension instead. This will be removed in 2.2") + fun requireConfigured(): NodeJsEnv { + return nodeJs().produceEnv(project.providers).get() + } companion object { const val EXTENSION_NAME: String = "kotlinNodeJs" diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootPlugin.kt index bfc02229cd664..0f48a344d78e5 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsRootPlugin.kt @@ -34,49 +34,40 @@ open class NodeJsRootPlugin : Plugin { override fun apply(project: Project) { MultiplePluginDeclarationDetector.detect(project) - project.plugins.apply(BasePlugin::class.java) - check(project == project.rootProject) { "NodeJsRootPlugin can be applied only to root project" } - val nodeJs = project.extensions.create( + project.plugins.apply(BasePlugin::class.java) + + val nodeJsRoot = project.extensions.create( NodeJsRootExtension.EXTENSION_NAME, NodeJsRootExtension::class.java, - project + project, + { NodeJsPlugin.apply(project) } ) val npm = project.extensions.create( NpmExtension.EXTENSION_NAME, NpmExtension::class.java, - project + project, + nodeJsRoot ) - addPlatform(project, nodeJs) + val nodeJs = NodeJsPlugin.apply(project) npm.nodeJsEnvironment.value( - project.provider { - nodeJs.requireConfigured() - } + nodeJs.produceEnv(project.providers) ).disallowChanges() - nodeJs.packageManagerExtension.convention( + nodeJsRoot.packageManagerExtension.convention( npm ) - val setupTask = project.registerTask(NodeJsSetupTask.NAME) { - it.group = TASKS_GROUP_NAME - it.description = "Download and install a local node/npm version" - it.configuration = project.provider { - project.configurations.detachedConfiguration(project.dependencies.create(it.ivyDependency)) - .also { conf -> conf.isTransitive = false } - } - } - val gradleNodeModulesProvider: Provider = GradleNodeModulesCache.registerIfAbsent( project, project.projectDir, - nodeJs.nodeModulesGradleCacheDirectory + nodeJsRoot.nodeModulesGradleCacheDirectory ) val setupFileHasherTask = project.registerTask(KotlinNpmCachesSetup.NAME) { @@ -86,7 +77,9 @@ open class NodeJsRootPlugin : Plugin { } val npmInstall = project.registerTask(KotlinNpmInstallTask.NAME) { npmInstall -> - npmInstall.dependsOn(setupTask) + with(nodeJs) { + npmInstall.dependsOn(project.nodeJsSetupTaskProvider) + } npmInstall.dependsOn(setupFileHasherTask) npmInstall.group = TASKS_GROUP_NAME npmInstall.description = "Find, download and link NPM dependencies and projects" @@ -105,13 +98,13 @@ open class NodeJsRootPlugin : Plugin { project.registerTask(PACKAGE_JSON_UMBRELLA_TASK_NAME) - nodeJs.resolver = KotlinRootNpmResolver( + nodeJsRoot.resolver = KotlinRootNpmResolver( project.name, project.version.toString(), TasksRequirements(), - nodeJs.versions, - nodeJs.projectPackagesDirectory, - nodeJs.rootProjectDir, + nodeJsRoot.versions, + nodeJsRoot.projectPackagesDirectory, + nodeJsRoot.rootProjectDir, ) val objectFactory = project.objects @@ -119,14 +112,14 @@ open class NodeJsRootPlugin : Plugin { val npmResolutionManager: Provider = KotlinNpmResolutionManager.registerIfAbsent( project, objectFactory.providerWithLazyConvention { - nodeJs.resolver.close() + nodeJsRoot.resolver.close() }, gradleNodeModulesProvider, - nodeJs.projectPackagesDirectory + nodeJsRoot.projectPackagesDirectory ) val rootPackageJson = project.tasks.register(RootPackageJsonTask.NAME, RootPackageJsonTask::class.java) { task -> - task.dependsOn(nodeJs.npmCachesSetupTaskProvider) + task.dependsOn(nodeJsRoot.npmCachesSetupTaskProvider) task.group = TASKS_GROUP_NAME task.description = "Create root package.json" @@ -141,10 +134,10 @@ open class NodeJsRootPlugin : Plugin { configureRequiresNpmDependencies(project, rootPackageJson) - val packageJsonUmbrella = nodeJs + val packageJsonUmbrella = nodeJsRoot .packageJsonUmbrellaTaskProvider - nodeJs.rootPackageJsonTaskProvider.configure { + nodeJsRoot.rootPackageJsonTaskProvider.configure { it.dependsOn(packageJsonUmbrella) } @@ -155,10 +148,10 @@ open class NodeJsRootPlugin : Plugin { project.tasks.register(LockCopyTask.STORE_PACKAGE_LOCK_NAME, LockStoreTask::class.java) { task -> task.dependsOn(npmInstall) - task.inputFile.set(nodeJs.rootPackageDirectory.map { it.file(LockCopyTask.PACKAGE_LOCK) }) + task.inputFile.set(nodeJsRoot.rootPackageDirectory.map { it.file(LockCopyTask.PACKAGE_LOCK) }) task.additionalInputFiles.from( - nodeJs.rootPackageDirectory.map { it.file(LockCopyTask.YARN_LOCK) } + nodeJsRoot.rootPackageDirectory.map { it.file(LockCopyTask.YARN_LOCK) } ) task.additionalInputFiles.from( task.outputDirectory.map { it.file(LockCopyTask.YARN_LOCK) } @@ -180,12 +173,12 @@ open class NodeJsRootPlugin : Plugin { project.tasks.register(LockCopyTask.UPGRADE_PACKAGE_LOCK, LockStoreTask::class.java) { task -> task.dependsOn(npmInstall) - task.inputFile.set(nodeJs.rootPackageDirectory.map { it.file(LockCopyTask.PACKAGE_LOCK) }) + task.inputFile.set(nodeJsRoot.rootPackageDirectory.map { it.file(LockCopyTask.PACKAGE_LOCK) }) task.outputDirectory.set(npm.lockFileDirectory) task.fileName.set(npm.lockFileName) task.additionalInputFiles.from( - nodeJs.rootPackageDirectory.map { it.file(LockCopyTask.YARN_LOCK) } + nodeJsRoot.rootPackageDirectory.map { it.file(LockCopyTask.YARN_LOCK) } ) task.additionalInputFiles.from( task.outputDirectory.map { it.file(LockCopyTask.YARN_LOCK) } @@ -211,7 +204,7 @@ open class NodeJsRootPlugin : Plugin { task.additionalInputFiles.from( npm.lockFileDirectory.map { it.file(LockCopyTask.YARN_LOCK) } ) - task.outputDirectory.set(nodeJs.rootPackageDirectory) + task.outputDirectory.set(nodeJsRoot.rootPackageDirectory) task.fileName.set(LockCopyTask.PACKAGE_LOCK) task.onlyIf { val inputFileExists = task.inputFile.getOrNull()?.asFile?.exists() == true @@ -233,7 +226,7 @@ open class NodeJsRootPlugin : Plugin { ).disallowChanges() npmInstall.configure { - it.dependsOn(nodeJs.packageManagerExtension.map { it.preInstallTasks }) + it.dependsOn(nodeJsRoot.packageManagerExtension.map { it.preInstallTasks }) } npmInstall.configure { @@ -241,7 +234,7 @@ open class NodeJsRootPlugin : Plugin { } project.tasks.register("node" + CleanDataTask.NAME_SUFFIX, CleanDataTask::class.java) { - it.cleanableStoreProvider = project.provider { nodeJs.requireConfigured().cleanableStore } + it.cleanableStoreProvider = nodeJs.produceEnv(project.providers).map { it.cleanableStore } it.group = TASKS_GROUP_NAME it.description = "Clean unused local node version" } @@ -249,24 +242,10 @@ open class NodeJsRootPlugin : Plugin { val propertiesProvider = PropertiesProvider(project) if (propertiesProvider.yarn) { - YarnPlugin.apply(project) + project.plugins.apply(YarnPlugin::class.java) } } - // from https://github.com/node-gradle/gradle-node-plugin - private fun addPlatform(project: Project, extension: NodeJsRootExtension) { - val uname = project.providers.unameExecResult - - extension.platform.value( - project.providers.systemProperty("os.name") - .zip( - project.providers.systemProperty("os.arch") - ) { name, arch -> - parsePlatform(name, arch, uname) - } - ).disallowChanges() - } - // Yes, we need to break Task Configuration Avoidance here // In case when we need to create package.json's files and execute kotlinNpmInstall, // We need to configure all RequiresNpmDependencies tasks to install them, @@ -312,7 +291,7 @@ open class NodeJsRootPlugin : Plugin { return rootProject.extensions.getByName(NodeJsRootExtension.EXTENSION_NAME) as NodeJsRootExtension } - val Project.kotlinNodeJsExtension: NodeJsRootExtension + val Project.kotlinNodeJsRootExtension: NodeJsRootExtension get() = extensions.getByName(NodeJsRootExtension.EXTENSION_NAME).castIsolatedKotlinPluginClassLoaderAware() val Project.kotlinNpmResolutionManager: Provider diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsSetupTask.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsSetupTask.kt index a918eab4f766c..d3e23410330a4 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsSetupTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsSetupTask.kt @@ -3,17 +3,17 @@ package org.jetbrains.kotlin.gradle.targets.js.nodejs import org.gradle.api.tasks.Internal import org.gradle.work.DisableCachingByDefault import org.jetbrains.kotlin.gradle.targets.js.AbstractSetupTask -import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension +import org.jetbrains.kotlin.gradle.utils.getFile import java.io.File import java.nio.file.Files import java.nio.file.Path import java.nio.file.Paths +import javax.inject.Inject @DisableCachingByDefault -abstract class NodeJsSetupTask : AbstractSetupTask() { - @Transient - @get:Internal - override val settings = project.rootProject.kotlinNodeJsExtension +abstract class NodeJsSetupTask @Inject constructor( + settings: NodeJsEnvSpec +) : AbstractSetupTask(settings) { @get:Internal override val artifactPattern: String @@ -27,9 +27,14 @@ abstract class NodeJsSetupTask : AbstractSetupTask { return listOf( nodeJs .rootPackageDir + .getFile() .resolve(NpmProject.PACKAGE_JSON) ) } @@ -64,7 +65,7 @@ class Npm : NpmApiExecution { packageManagerEnvironment: NpmEnvironment, cliArgs: List, ) { - val nodeJsWorldDir = nodeJs.rootPackageDir + val nodeJsWorldDir = nodeJs.rootPackageDir.getFile() npmExec( services, diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmApiExecution.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmApiExecution.kt index b8d3da099d728..01cf204696159 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmApiExecution.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmApiExecution.kt @@ -5,9 +5,12 @@ package org.jetbrains.kotlin.gradle.targets.js.npm +import org.gradle.api.file.Directory import org.gradle.api.logging.Logger +import org.gradle.api.provider.Provider import org.gradle.internal.service.ServiceRegistry import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsEnv +import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension import org.jetbrains.kotlin.gradle.targets.js.nodejs.PackageManagerEnvironment import org.jetbrains.kotlin.gradle.targets.js.npm.resolved.PreparedKotlinCompilationNpmResolution import java.io.File @@ -32,7 +35,7 @@ interface NpmApiExecution : Serializable { logger: Logger, nodeJs: NodeJsEnvironment, packageManagerEnvironment: @UnsafeVariance T, - cliArgs: List + cliArgs: List, ) companion object { @@ -42,14 +45,13 @@ interface NpmApiExecution : Serializable { } data class NodeJsEnvironment( - val rootPackageDir: File, + val rootPackageDir: Provider, val nodeExecutable: String, - val packageManager: NpmApiExecution + val packageManager: NpmApiExecution, ) : Serializable -internal val NodeJsEnv.asNodeJsEnvironment - get() = NodeJsEnvironment( - rootPackageDir, - executable, - packageManager - ) \ No newline at end of file +internal fun asNodeJsEnvironment(nodeJsRoot: NodeJsRootExtension, nodeJsEnv: NodeJsEnv) = NodeJsEnvironment( + nodeJsRoot.rootPackageDirectory, + nodeJsEnv.executable, + nodeJsRoot.packageManagerExtension.get().packageManager +) \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmExtension.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmExtension.kt index 02a1fc67807bd..52fa7b89fea46 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmExtension.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmExtension.kt @@ -15,11 +15,13 @@ import org.gradle.api.tasks.TaskProvider import org.jetbrains.kotlin.gradle.internal.ConfigurationPhaseAware import org.jetbrains.kotlin.gradle.logging.kotlinInfo import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsEnv +import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin import org.jetbrains.kotlin.gradle.targets.js.nodejs.NpmApiExtension open class NpmExtension( val project: Project, + val nodeJsRoot: NodeJsRootExtension ) : ConfigurationPhaseAware(), NpmApiExtension { init { check(project == project.rootProject) @@ -35,9 +37,7 @@ open class NpmExtension( } override val additionalInstallOutput: FileCollection = project.objects.fileCollection().from( - { - nodeJsEnvironment.get().rootPackageDir.resolve("package-lock.json") - } + nodeJsRoot.rootPackageDirectory.map { it.file("package-lock.json") } ) override val preInstallTasks: ListProperty> = project.objects.listProperty(TaskProvider::class.java) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmProject.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmProject.kt index 7ec3629965256..34a5590134381 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmProject.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmProject.kt @@ -16,7 +16,8 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.disambiguateName import org.jetbrains.kotlin.gradle.plugin.mpp.fileExtension import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsTargetDsl import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrCompilation -import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension +import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsPlugin.Companion.kotlinNodeJsEnvSpec +import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsRootExtension import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinPackageJsonTask import org.jetbrains.kotlin.gradle.utils.getFile import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly @@ -45,12 +46,17 @@ open class NpmProject(@Transient val compilation: KotlinJsIrCompilation) : Seria buildNpmProjectName() } + @delegate:Transient + val nodeJsRoot by lazy { + project.rootProject.kotlinNodeJsRootExtension + } + @delegate:Transient val nodeJs by lazy { - project.rootProject.kotlinNodeJsExtension + project.kotlinNodeJsEnvSpec } - val dir: Provider = nodeJs.projectPackagesDirectory.map { it.dir(name) } + val dir: Provider = nodeJsRoot.projectPackagesDirectory.map { it.dir(name) } val target: KotlinJsTargetDsl get() = compilation.target as KotlinJsTargetDsl @@ -86,7 +92,7 @@ open class NpmProject(@Transient val compilation: KotlinJsIrCompilation) : Seria } private val nodeExecutable by lazy { - nodeJs.requireConfigured().executable + nodeJs.produceEnv(project.providers).get().executable } fun useTool( diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmResolverPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmResolverPlugin.kt index cd6c67fdc3483..3e0c9da3daa27 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmResolverPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/NpmResolverPlugin.kt @@ -7,17 +7,19 @@ package org.jetbrains.kotlin.gradle.targets.js.npm import org.gradle.api.Plugin import org.gradle.api.Project +import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsPlugin import org.jetbrains.kotlin.gradle.utils.whenEvaluated import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin -import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension +import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsRootExtension import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.implementing import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest class NpmResolverPlugin : Plugin { override fun apply(project: Project) { - val nodeJs = NodeJsRootPlugin.apply(project.rootProject) - project.rootProject.kotlinNodeJsExtension.resolver.addProject(project) - val kotlinNodeJsTaskProvidersExtension = project.rootProject.kotlinNodeJsExtension + val nodeJsRoot = NodeJsRootPlugin.apply(project.rootProject) + NodeJsPlugin.apply(project) + project.rootProject.kotlinNodeJsRootExtension.resolver.addProject(project) + val kotlinNodeJsTaskProvidersExtension = project.rootProject.kotlinNodeJsRootExtension project.whenEvaluated { project.tasks.implementing(RequiresNpmDependencies::class) .configureEach { task -> @@ -26,13 +28,13 @@ class NpmResolverPlugin : Plugin { // KotlinJsTest delegates npm dependencies to testFramework, // which can be defined after this configure action if (task !is KotlinJsTest) { - nodeJs.taskRequirements.addTaskRequirements(task) + nodeJsRoot.taskRequirements.addTaskRequirements(task) } task.dependsOn( kotlinNodeJsTaskProvidersExtension.npmInstallTaskProvider, ) - task.dependsOn(nodeJs.packageManagerExtension.map { it.postInstallTasks }) + task.dependsOn(nodeJsRoot.packageManagerExtension.map { it.postInstallTasks }) } } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/resolver/KotlinCompilationNpmResolver.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/resolver/KotlinCompilationNpmResolver.kt index 3e75d39b98751..68b65fc718cf1 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/resolver/KotlinCompilationNpmResolver.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/resolver/KotlinCompilationNpmResolver.kt @@ -27,7 +27,7 @@ import org.jetbrains.kotlin.gradle.plugin.sources.sourceSetDependencyConfigurati import org.jetbrains.kotlin.gradle.plugin.usesPlatformOf import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrCompilation import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTarget -import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension +import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsRootExtension import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNpmResolutionManager import org.jetbrains.kotlin.gradle.targets.js.npm.* import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinPackageJsonTask @@ -64,7 +64,7 @@ class KotlinCompilationNpmResolver( val publicPackageJsonTaskHolder: TaskProvider = run { val npmResolutionManager = project.kotlinNpmResolutionManager - val nodeJsTaskProviders = project.rootProject.kotlinNodeJsExtension + val nodeJsTaskProviders = project.rootProject.kotlinNodeJsRootExtension project.registerTask( npmProject.publicPackageJsonTaskName ) { diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/tasks/KotlinNpmInstallTask.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/tasks/KotlinNpmInstallTask.kt index b1241e78fd1b9..4a4aec62f746c 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/tasks/KotlinNpmInstallTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/tasks/KotlinNpmInstallTask.kt @@ -9,21 +9,20 @@ import org.gradle.api.DefaultTask import org.gradle.api.file.Directory import org.gradle.api.file.FileCollection import org.gradle.api.file.RegularFile -import org.gradle.api.provider.ListProperty import org.gradle.api.provider.Provider import org.gradle.api.tasks.* import org.gradle.work.DisableCachingByDefault import org.gradle.work.NormalizeLineEndings +import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsEnvSpec +import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsPlugin.Companion.kotlinNodeJsEnvSpec import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension -import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension +import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsRootExtension import org.jetbrains.kotlin.gradle.targets.js.npm.KotlinNpmResolutionManager import org.jetbrains.kotlin.gradle.targets.js.npm.NpmProject import org.jetbrains.kotlin.gradle.targets.js.npm.UsesKotlinNpmResolutionManager import org.jetbrains.kotlin.gradle.targets.js.npm.asNodeJsEnvironment import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.KotlinRootNpmResolver import org.jetbrains.kotlin.gradle.utils.getFile -import org.jetbrains.kotlin.gradle.utils.listProperty -import org.jetbrains.kotlin.gradle.utils.providerWithLazyConvention import java.io.File @DisableCachingByDefault @@ -37,23 +36,26 @@ abstract class KotlinNpmInstallTask : // Only in configuration phase // Not part of configuration caching - private val nodeJs: NodeJsRootExtension - get() = project.rootProject.kotlinNodeJsExtension + private val nodeJsRoot: NodeJsRootExtension + get() = project.rootProject.kotlinNodeJsRootExtension + + private val nodeJs: NodeJsEnvSpec + get() = project.rootProject.kotlinNodeJsEnvSpec private val rootResolver: KotlinRootNpmResolver - get() = nodeJs.resolver + get() = nodeJsRoot.resolver // ----- private val nodsJsEnvironment by lazy { - nodeJs.requireConfigured().asNodeJsEnvironment + asNodeJsEnvironment(nodeJsRoot, nodeJs.produceEnv(project.providers).get()) } private val packageManagerEnv by lazy { - nodeJs.packageManagerExtension.get().environment + nodeJsRoot.packageManagerExtension.get().environment } - private val packagesDir: Provider = nodeJs.projectPackagesDirectory + private val packagesDir: Provider = nodeJsRoot.projectPackagesDirectory @Input val args: MutableList = mutableListOf() @@ -63,7 +65,7 @@ abstract class KotlinNpmInstallTask : @get:NormalizeLineEndings @get:InputFiles val preparedFiles: Collection by lazy { - nodeJs.packageManagerExtension.get().packageManager.preparedFiles(nodsJsEnvironment) + nodeJsRoot.packageManagerExtension.get().packageManager.preparedFiles(nodsJsEnvironment) } @get:PathSensitive(PathSensitivity.RELATIVE) @@ -82,7 +84,7 @@ abstract class KotlinNpmInstallTask : @get:OutputFiles val additionalFiles: FileCollection by lazy { - nodeJs.packageManagerExtension.get().additionalInstallOutput + nodeJsRoot.packageManagerExtension.get().additionalInstallOutput } @Deprecated( @@ -90,7 +92,7 @@ abstract class KotlinNpmInstallTask : replaceWith = ReplaceWith("additionalFiles") ) @get:Internal - val yarnLockFile: Provider = nodeJs.rootPackageDirectory.map { it.file("yarn.lock") } + val yarnLockFile: Provider = nodeJsRoot.rootPackageDirectory.map { it.file("yarn.lock") } @Suppress("DEPRECATION") @Deprecated( @@ -104,7 +106,7 @@ abstract class KotlinNpmInstallTask : // node_modules as OutputDirectory is performance problematic // so input will only be existence of its directory @get:Internal - val nodeModules: Provider = nodeJs.rootPackageDirectory.map { it.dir("node_modules") } + val nodeModules: Provider = nodeJsRoot.rootPackageDirectory.map { it.dir("node_modules") } @TaskAction fun resolve() { diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/tasks/KotlinPackageJsonTask.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/tasks/KotlinPackageJsonTask.kt index 7672060eb396d..8eb0f54f4d062 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/tasks/KotlinPackageJsonTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/tasks/KotlinPackageJsonTask.kt @@ -17,7 +17,7 @@ import org.gradle.work.NormalizeLineEndings import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrCompilation import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin -import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension +import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsRootExtension import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNpmResolutionManager import org.jetbrains.kotlin.gradle.targets.js.npm.* import org.jetbrains.kotlin.gradle.targets.js.npm.resolver.* @@ -36,7 +36,7 @@ abstract class KotlinPackageJsonTask : // Not part of configuration caching private val nodeJs: NodeJsRootExtension - get() = project.rootProject.kotlinNodeJsExtension + get() = project.rootProject.kotlinNodeJsRootExtension private val rootResolver: KotlinRootNpmResolver get() = nodeJs.resolver @@ -131,7 +131,7 @@ abstract class KotlinPackageJsonTask : val target = compilation.target val project = target.project val npmProject = compilation.npmProject - val nodeJsTaskProviders = project.rootProject.kotlinNodeJsExtension + val nodeJsTaskProviders = project.rootProject.kotlinNodeJsRootExtension val npmCachesSetupTask = nodeJsTaskProviders.npmCachesSetupTaskProvider val packageJsonTaskName = npmProject.packageJsonTaskName diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/tasks/RootPackageJsonTask.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/tasks/RootPackageJsonTask.kt index cc65e1b601e53..5ad6b4ee1a509 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/tasks/RootPackageJsonTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/npm/tasks/RootPackageJsonTask.kt @@ -7,13 +7,13 @@ package org.jetbrains.kotlin.gradle.targets.js.npm.tasks import org.gradle.api.DefaultTask import org.gradle.api.file.Directory -import org.gradle.api.file.FileCollection import org.gradle.api.file.RegularFile import org.gradle.api.provider.Provider import org.gradle.api.tasks.* import org.gradle.work.DisableCachingByDefault import org.gradle.work.NormalizeLineEndings -import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension +import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsPlugin.Companion.kotlinNodeJsEnvSpec +import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsRootExtension import org.jetbrains.kotlin.gradle.targets.js.npm.NpmProject import org.jetbrains.kotlin.gradle.targets.js.npm.UsesKotlinNpmResolutionManager import org.jetbrains.kotlin.gradle.targets.js.npm.asNodeJsEnvironment @@ -32,28 +32,31 @@ abstract class RootPackageJsonTask : // Only in configuration phase // Not part of configuration caching + private val nodeJsRoot + get() = project.rootProject.kotlinNodeJsRootExtension + private val nodeJs - get() = project.rootProject.kotlinNodeJsExtension + get() = project.rootProject.kotlinNodeJsEnvSpec private val rootResolver: KotlinRootNpmResolver - get() = nodeJs.resolver + get() = nodeJsRoot.resolver private val packagesDir: Provider - get() = nodeJs.projectPackagesDirectory + get() = nodeJsRoot.projectPackagesDirectory // ----- private val nodeJsEnvironment by lazy { - nodeJs.requireConfigured().asNodeJsEnvironment + asNodeJsEnvironment(nodeJsRoot, nodeJs.produceEnv(project.providers).get()) } private val packageManagerEnv by lazy { - nodeJs.packageManagerExtension.get().environment + nodeJsRoot.packageManagerExtension.get().environment } @get:OutputFile val rootPackageJsonFile: Provider = - nodeJs.rootPackageDirectory.map { it.file(NpmProject.PACKAGE_JSON) } + nodeJsRoot.rootPackageDirectory.map { it.file(NpmProject.PACKAGE_JSON) } @Deprecated( diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/KotlinJsTest.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/KotlinJsTest.kt index c5e98171687d4..a87a31ab880a8 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/KotlinJsTest.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/KotlinJsTest.kt @@ -15,14 +15,13 @@ import org.gradle.work.NormalizeLineEndings import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesTestExecutionSpec import org.jetbrains.kotlin.gradle.targets.js.RequiredKotlinJsDependency import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrCompilation -import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension +import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsPlugin.Companion.kotlinNodeJsEnvSpec import org.jetbrains.kotlin.gradle.targets.js.npm.RequiresNpmDependencies import org.jetbrains.kotlin.gradle.targets.js.testing.karma.KotlinKarma import org.jetbrains.kotlin.gradle.targets.js.testing.mocha.KotlinMocha import org.jetbrains.kotlin.gradle.tasks.KotlinTest import org.jetbrains.kotlin.gradle.utils.domainObjectSet import org.jetbrains.kotlin.gradle.utils.getFile -import org.jetbrains.kotlin.gradle.utils.getValue import org.jetbrains.kotlin.gradle.utils.newFileProperty import javax.inject.Inject @@ -32,13 +31,13 @@ abstract class KotlinJsTest constructor( @Transient @Internal - override var compilation: KotlinJsIrCompilation + override var compilation: KotlinJsIrCompilation, ) : KotlinTest(), RequiresNpmDependencies { @Transient - private val nodeJs = project.rootProject.kotlinNodeJsExtension + private val nodeJs = project.kotlinNodeJsEnvSpec - private val nodeExecutable by project.provider { nodeJs.requireConfigured().executable } + private val nodeExecutable = nodeJs.produceEnv(project.providers).map { it.executable } @Input var environment = mutableMapOf() @@ -155,7 +154,7 @@ constructor( override fun createTestExecutionSpec(): TCServiceMessagesTestExecutionSpec { val forkOptions = DefaultProcessForkOptions(fileResolver) forkOptions.workingDir = testFramework!!.workingDir.getFile() - forkOptions.executable = nodeExecutable + forkOptions.executable = nodeExecutable.get() environment.forEach { (key, value) -> forkOptions.environment(key, value) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/KotlinWasmD8.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/KotlinWasmD8.kt index dfe8d8c1e64c0..1ed77cad3901a 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/KotlinWasmD8.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/KotlinWasmD8.kt @@ -8,16 +8,17 @@ package org.jetbrains.kotlin.gradle.targets.js.testing import org.gradle.api.file.Directory import org.gradle.api.provider.Provider import org.gradle.process.ProcessForkOptions +import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesClientSettings import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesTestExecutionSpec import org.jetbrains.kotlin.gradle.targets.js.RequiredKotlinJsDependency -import org.jetbrains.kotlin.gradle.targets.js.d8.D8RootPlugin +import org.jetbrains.kotlin.gradle.targets.js.d8.D8Plugin import org.jetbrains.kotlin.gradle.targets.js.internal.parseNodeJsStackTraceAsJvm import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrCompilation import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject import org.jetbrains.kotlin.gradle.targets.js.writeWasmUnitTestRunner -import org.jetbrains.kotlin.gradle.utils.getValue +@ExperimentalWasmDsl internal class KotlinWasmD8(kotlinJsTest: KotlinJsTest) : KotlinJsTestFramework { override val settingsState: String = "KotlinWasmD8" @@ -26,8 +27,8 @@ internal class KotlinWasmD8(kotlinJsTest: KotlinJsTest) : KotlinJsTestFramework @Transient override val compilation: KotlinJsIrCompilation = kotlinJsTest.compilation - private val d8 = D8RootPlugin.apply(kotlinJsTest.project.rootProject) - private val d8Executable by kotlinJsTest.project.provider { d8.requireConfigured().executable } + private val d8 = D8Plugin.apply(kotlinJsTest.project) + private val d8Executable = d8.d8EnvSpec.produceEnv(compilation.project.providers).map { it.executable } override val workingDir: Provider = compilation.npmProject.dir @@ -40,7 +41,7 @@ internal class KotlinWasmD8(kotlinJsTest: KotlinJsTest) : KotlinJsTestFramework val compiledFile = task.inputFileProperty.get().asFile val testRunnerFile = writeWasmUnitTestRunner(workingDir.get().asFile, compiledFile) - forkOptions.executable = d8Executable + forkOptions.executable = d8Executable.get() forkOptions.workingDir = compiledFile.parentFile val clientSettings = TCServiceMessagesClientSettings( diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/karma/KotlinKarma.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/karma/KotlinKarma.kt index 4465836eb299b..5a6601d241885 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/karma/KotlinKarma.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/karma/KotlinKarma.kt @@ -30,7 +30,7 @@ import org.jetbrains.kotlin.gradle.targets.js.dsl.WebpackRulesDsl.Companion.webp import org.jetbrains.kotlin.gradle.targets.js.internal.parseNodeJsStackTraceAsJvm import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrCompilation import org.jetbrains.kotlin.gradle.targets.js.jsQuoted -import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension +import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsRootExtension import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject import org.jetbrains.kotlin.gradle.targets.js.testing.* import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig @@ -55,7 +55,7 @@ class KotlinKarma( private val platformType = compilation.platformType @Transient - private val nodeJs = project.rootProject.kotlinNodeJsExtension + private val nodeJs = project.rootProject.kotlinNodeJsRootExtension private val nodeRootPackageDir by lazy { nodeJs.rootPackageDirectory } private val versions = nodeJs.versions diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/mocha/KotlinMocha.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/mocha/KotlinMocha.kt index 83f8d0d2b437c..1dcba1b20f4fa 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/mocha/KotlinMocha.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/testing/mocha/KotlinMocha.kt @@ -11,26 +11,24 @@ import org.gradle.api.provider.Provider import org.gradle.process.ProcessForkOptions import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesClientSettings import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesTestExecutionSpec -import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesTestExecutor import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType import org.jetbrains.kotlin.gradle.targets.js.RequiredKotlinJsDependency import org.jetbrains.kotlin.gradle.targets.js.internal.parseNodeJsStackTraceAsJvm import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrCompilation -import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension +import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsRootExtension import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTestFramework import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinTestRunnerCliArgs import org.jetbrains.kotlin.gradle.utils.getFile import org.jetbrains.kotlin.gradle.utils.getValue -import java.nio.file.Path class KotlinMocha(@Transient override val compilation: KotlinJsIrCompilation, private val basePath: String) : KotlinJsTestFramework { @Transient private val project: Project = compilation.target.project private val npmProject = compilation.npmProject - private val versions = project.rootProject.kotlinNodeJsExtension.versions + private val versions = project.rootProject.kotlinNodeJsRootExtension.versions private val npmProjectDir by project.provider { npmProject.dir } override val workingDir: Provider diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/typescript/TypeScriptValidationTask.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/typescript/TypeScriptValidationTask.kt index 0e57a8ed313a5..b67bfb4fcfe50 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/typescript/TypeScriptValidationTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/typescript/TypeScriptValidationTask.kt @@ -15,7 +15,7 @@ import org.jetbrains.kotlin.gradle.internal.execWithProgress import org.jetbrains.kotlin.gradle.targets.js.RequiredKotlinJsDependency import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinIrJsGeneratedTSValidationStrategy import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrCompilation -import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension +import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsRootExtension import org.jetbrains.kotlin.gradle.targets.js.npm.RequiresNpmDependencies import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject import javax.inject.Inject @@ -32,7 +32,7 @@ constructor( @get:Internal @Transient - protected val nodeJs = project.rootProject.kotlinNodeJsExtension + protected val nodeJs = project.rootProject.kotlinNodeJsRootExtension private val versions = nodeJs.versions diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/webpack/KotlinWebpack.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/webpack/KotlinWebpack.kt index 5faac3bd0eb2d..bc837a206fed4 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/webpack/KotlinWebpack.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/webpack/KotlinWebpack.kt @@ -33,7 +33,7 @@ import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinWebpackRulesContainer import org.jetbrains.kotlin.gradle.targets.js.dsl.WebpackRulesDsl import org.jetbrains.kotlin.gradle.targets.js.dsl.WebpackRulesDsl.Companion.webpackRulesContainer import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrCompilation -import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension +import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsRootExtension import org.jetbrains.kotlin.gradle.targets.js.npm.RequiresNpmDependencies import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig.Mode @@ -55,7 +55,7 @@ constructor( private val objects: ObjectFactory, ) : DefaultTask(), RequiresNpmDependencies, WebpackRulesDsl, UsesBuildMetricsService { @Transient - private val nodeJs = project.rootProject.kotlinNodeJsExtension + private val nodeJs = project.rootProject.kotlinNodeJsRootExtension private val versions = nodeJs.versions private val rootPackageDir by lazy { nodeJs.rootPackageDirectory } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnPlugin.kt index f2172da6e900f..0d4d706a78a0f 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnPlugin.kt @@ -7,14 +7,19 @@ package org.jetbrains.kotlin.gradle.targets.js.yarn import org.gradle.api.Plugin import org.gradle.api.Project +import org.gradle.api.model.ObjectFactory +import org.gradle.api.plugins.ExtensionContainer import org.jetbrains.kotlin.gradle.targets.js.MultiplePluginDeclarationDetector +import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsPlugin.Companion.kotlinNodeJsEnvSpec import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin -import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsExtension +import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin.Companion.kotlinNodeJsRootExtension import org.jetbrains.kotlin.gradle.targets.js.npm.LockCopyTask import org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmInstallTask import org.jetbrains.kotlin.gradle.tasks.CleanDataTask import org.jetbrains.kotlin.gradle.tasks.registerTask import org.jetbrains.kotlin.gradle.utils.detachedResolvable +import org.jetbrains.kotlin.gradle.utils.listProperty +import org.jetbrains.kotlin.gradle.utils.providerWithLazyConvention open class YarnPlugin : Plugin { override fun apply(project: Project): Unit = project.run { @@ -24,26 +29,39 @@ open class YarnPlugin : Plugin { "YarnPlugin can be applied only to root project" } - val yarnRootExtension = this.extensions.create(YarnRootExtension.YARN, YarnRootExtension::class.java, this) NodeJsRootPlugin.apply(project) - val nodeJs = this.kotlinNodeJsExtension - val nodeJsTaskProviders = this.kotlinNodeJsExtension + val nodeJsRoot = this.kotlinNodeJsRootExtension + val nodeJs = this.kotlinNodeJsEnvSpec + + val yarnSpec = project.extensions.createYarnEnvSpec() + + val yarnRootExtension = this.extensions.create( + YarnRootExtension.YARN, + YarnRootExtension::class.java, + this, + nodeJsRoot, + yarnSpec + ) + + yarnSpec.initializeYarnEnvSpec(objects, yarnRootExtension) yarnRootExtension.platform.value(nodeJs.platform) .disallowChanges() - nodeJs.packageManagerExtension.set( + nodeJsRoot.packageManagerExtension.set( yarnRootExtension ) - val setupTask = registerTask(YarnSetupTask.NAME) { - it.dependsOn(nodeJsTaskProviders.nodeJsSetupTaskProvider) + val setupTask = registerTask(YarnSetupTask.NAME, listOf(yarnSpec)) { + with(nodeJs) { + it.dependsOn(project.nodeJsSetupTaskProvider) + } it.group = NodeJsRootPlugin.TASKS_GROUP_NAME it.description = "Download and install a local yarn version" - it.configuration = provider { - this.project.configurations.detachedResolvable(this.project.dependencies.create(it.ivyDependency)) + it.configuration = it.ivyDependencyProvider.map { ivyDependency -> + this.project.configurations.detachedResolvable(this.project.dependencies.create(ivyDependency)) .also { conf -> conf.isTransitive = false } } } @@ -55,9 +73,7 @@ open class YarnPlugin : Plugin { } yarnRootExtension.nodeJsEnvironment.value( - project.provider { - nodeJs.requireConfigured() - } + nodeJs.produceEnv(project.providers) ).disallowChanges() tasks.register("yarn" + CleanDataTask.NAME_SUFFIX, CleanDataTask::class.java) { @@ -67,7 +83,7 @@ open class YarnPlugin : Plugin { tasks.register(STORE_YARN_LOCK_NAME, YarnLockStoreTask::class.java) { task -> task.dependsOn(kotlinNpmInstall) - task.inputFile.set(nodeJs.rootPackageDirectory.map { it.file(LockCopyTask.YARN_LOCK) }) + task.inputFile.set(nodeJsRoot.rootPackageDirectory.map { it.file(LockCopyTask.YARN_LOCK) }) task.outputDirectory.set(yarnRootExtension.lockFileDirectory) task.fileName.set(yarnRootExtension.lockFileName) @@ -84,7 +100,7 @@ open class YarnPlugin : Plugin { tasks.register(UPGRADE_YARN_LOCK, YarnLockCopyTask::class.java) { task -> task.dependsOn(kotlinNpmInstall) - task.inputFile.set(nodeJs.rootPackageDirectory.map { it.file(LockCopyTask.YARN_LOCK) }) + task.inputFile.set(nodeJsRoot.rootPackageDirectory.map { it.file(LockCopyTask.YARN_LOCK) }) task.outputDirectory.set(yarnRootExtension.lockFileDirectory) task.fileName.set(yarnRootExtension.lockFileName) } @@ -92,7 +108,7 @@ open class YarnPlugin : Plugin { tasks.register(RESTORE_YARN_LOCK_NAME, YarnLockCopyTask::class.java) { val lockFile = yarnRootExtension.lockFileDirectory.resolve(yarnRootExtension.lockFileName) it.inputFile.set(yarnRootExtension.lockFileDirectory.resolve(yarnRootExtension.lockFileName)) - it.outputDirectory.set(nodeJs.rootPackageDirectory) + it.outputDirectory.set(nodeJsRoot.rootPackageDirectory) it.fileName.set(LockCopyTask.YARN_LOCK) it.onlyIf { lockFile.exists() @@ -108,6 +124,36 @@ open class YarnPlugin : Plugin { ).disallowChanges() } + private fun ExtensionContainer.createYarnEnvSpec(): YarnRootEnvSpec { + return create( + YarnRootEnvSpec.YARN, + YarnRootEnvSpec::class.java + ) + } + + private fun YarnRootEnvSpec.initializeYarnEnvSpec( + objectFactory: ObjectFactory, + yarnRootExtension: YarnRootExtension, + ) { + download.convention(yarnRootExtension.downloadProperty) + downloadBaseUrl.convention(yarnRootExtension.downloadBaseUrlProperty) + installationDirectory.convention(yarnRootExtension.installationDirectory) + version.convention(yarnRootExtension.versionProperty) + command.convention(yarnRootExtension.commandProperty) + platform.convention(yarnRootExtension.platform) + ignoreScripts.convention(objectFactory.providerWithLazyConvention { yarnRootExtension.ignoreScripts }) + yarnLockMismatchReport.convention(objectFactory.providerWithLazyConvention { yarnRootExtension.yarnLockMismatchReport }) + reportNewYarnLock.convention(objectFactory.providerWithLazyConvention { yarnRootExtension.reportNewYarnLock }) + yarnLockAutoReplace.convention(objectFactory.providerWithLazyConvention { yarnRootExtension.yarnLockAutoReplace }) + resolutions.convention( + objectFactory.listProperty().value( + objectFactory.providerWithLazyConvention { + yarnRootExtension.resolutions + } + ) + ) + } + companion object { fun apply(project: Project): YarnRootExtension { val rootProject = project.rootProject diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnRootEnvSpec.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnRootEnvSpec.kt new file mode 100644 index 0000000000000..5deb5b2f52ee1 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnRootEnvSpec.kt @@ -0,0 +1,106 @@ +/* + * Copyright 2010-2020 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.gradle.targets.js.yarn + +import org.gradle.api.provider.ListProperty +import org.gradle.api.provider.Property +import org.gradle.api.provider.Provider +import org.gradle.api.provider.ProviderFactory +import org.jetbrains.kotlin.gradle.targets.js.EnvSpec +import org.jetbrains.kotlin.gradle.targets.js.nodejs.Platform +import org.jetbrains.kotlin.gradle.tasks.internal.CleanableStore +import org.jetbrains.kotlin.gradle.utils.getFile + +/** + * Spec for Yarn - package manager to install NPM dependencies + */ +abstract class YarnRootEnvSpec : EnvSpec() { + + /** + * Specify a platform information with name and architecture + */ + internal abstract val platform: Property + + /** + * Specify whether to not run install without custom package scripts. + * It is useful for security + * + * Default: true + */ + abstract val ignoreScripts: Property + + /** + * Specify a behaviour if yarn.lock file was changed + * + * Default: FAIL + */ + abstract val yarnLockMismatchReport: Property + + /** + * Specify whether to fail a build if new yarn.lock file was generated during the build + * + * Default: false + */ + abstract val reportNewYarnLock: Property + + /** + * Specify whether to replace already existing yarn.lock file with newly generated yarn.lock file + * + * Default: false + */ + abstract val yarnLockAutoReplace: Property + + /** + * Specify replacements of versions of installed NPM dependencies + * + * Details: https://classic.yarnpkg.com/lang/en/docs/selective-version-resolutions/ + */ + abstract val resolutions: ListProperty + + override fun produceEnv(providerFactory: ProviderFactory): Provider { + return providerFactory.provider { + val cleanableStore = CleanableStore[installationDirectory.getFile().path] + + val isWindows = platform.get().isWindows() + + val home = cleanableStore["yarn-v${version.get()}"].use() + + val downloadValue = download.get() + fun getExecutable( + command: String, + customCommand: String, + windowsExtension: String, + ): String { + val finalCommand = + if (isWindows && customCommand == command) "$command.$windowsExtension" else customCommand + return if (downloadValue) + home + .resolve("bin/yarn.js").absolutePath + else + finalCommand + } + + YarnEnv( + download = downloadValue, + downloadBaseUrl = downloadBaseUrl.orNull, + cleanableStore = cleanableStore, + dir = home, + executable = getExecutable("yarn", command.get(), "cmd"), + ivyDependency = "com.yarnpkg:yarn:${version.get()}@tar.gz", + ignoreScripts = ignoreScripts.get(), + yarnLockMismatchReport = yarnLockMismatchReport.get(), + reportNewYarnLock = reportNewYarnLock.get(), + yarnLockAutoReplace = yarnLockAutoReplace.get(), + yarnResolutions = resolutions.get() + ) + } + } + + companion object { + const val YARN: String = "kotlinYarnSpec" + } + +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnRootExtension.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnRootExtension.kt index 1ca3dc9f04258..f3bf54eb66940 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnRootExtension.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnRootExtension.kt @@ -7,23 +7,24 @@ package org.jetbrains.kotlin.gradle.targets.js.yarn import org.gradle.api.Action import org.gradle.api.Project -import org.gradle.api.Task +import org.gradle.api.file.DirectoryProperty import org.gradle.api.file.FileCollection import org.gradle.api.provider.ListProperty import org.gradle.api.tasks.TaskProvider import org.jetbrains.kotlin.gradle.logging.kotlinInfo import org.jetbrains.kotlin.gradle.targets.js.AbstractSettings -import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsEnv -import org.jetbrains.kotlin.gradle.targets.js.nodejs.NpmApiExtension +import org.jetbrains.kotlin.gradle.targets.js.nodejs.* import org.jetbrains.kotlin.gradle.targets.js.nodejs.Platform import org.jetbrains.kotlin.gradle.targets.js.npm.LockCopyTask import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin.Companion.RESTORE_YARN_LOCK_NAME import org.jetbrains.kotlin.gradle.targets.js.yarn.YarnPlugin.Companion.STORE_YARN_LOCK_NAME -import org.jetbrains.kotlin.gradle.tasks.internal.CleanableStore +import org.jetbrains.kotlin.gradle.utils.property import java.io.File open class YarnRootExtension( - val project: Project + val project: Project, + val nodeJsRoot: NodeJsRootExtension, + private val yarnSpec: YarnRootEnvSpec, ) : AbstractSettings(), NpmApiExtension { init { check(project == project.rootProject) @@ -42,23 +43,29 @@ open class YarnRootExtension( } override val additionalInstallOutput: FileCollection = project.objects.fileCollection().from( - { - nodeJsEnvironment.get().rootPackageDir.resolve(LockCopyTask.YARN_LOCK) - } + nodeJsRoot.rootPackageDirectory.map { it.file(LockCopyTask.YARN_LOCK) } ) override val preInstallTasks: ListProperty> = project.objects.listProperty(TaskProvider::class.java) override val postInstallTasks: ListProperty> = project.objects.listProperty(TaskProvider::class.java) - override var installationDir by Property(gradleHome.resolve("yarn")) + override val installationDirectory: DirectoryProperty = project.objects.directoryProperty() + .fileValue(gradleHome.resolve("yarn")) + + // value not convention because this property can be nullable to not add repository + override val downloadBaseUrlProperty: org.gradle.api.provider.Property = project.objects.property() + .value("https://github.com/yarnpkg/yarn/releases/download") - override var downloadBaseUrl: String? by Property("https://github.com/yarnpkg/yarn/releases/download") - override var version by Property("1.22.17") + override val versionProperty: org.gradle.api.provider.Property = project.objects.property() + .convention("1.22.17") - override var command by Property("yarn") + override val commandProperty: org.gradle.api.provider.Property = project.objects.property() + .convention("yarn") + + override val downloadProperty: org.gradle.api.provider.Property = project.objects.property() + .convention(true) - override var download by Property(true) var lockFileName by Property(LockCopyTask.YARN_LOCK) var lockFileDirectory: File by Property(project.rootDir.resolve(LockCopyTask.KOTLIN_JS_STORE)) @@ -95,33 +102,7 @@ open class YarnRootExtension( internal val nodeJsEnvironment: org.gradle.api.provider.Property = project.objects.property(NodeJsEnv::class.java) override fun finalizeConfiguration(): YarnEnv { - val cleanableStore = CleanableStore[installationDir.path] - - val isWindows = platform.get().isWindows() - - val home = cleanableStore["yarn-v$version"].use() - - fun getExecutable(command: String, customCommand: String, windowsExtension: String): String { - val finalCommand = if (isWindows && customCommand == command) "$command.$windowsExtension" else customCommand - return if (download) - home - .resolve("bin/yarn.js").absolutePath - else - finalCommand - } - return YarnEnv( - download = download, - downloadBaseUrl = downloadBaseUrl, - cleanableStore = cleanableStore, - dir = home, - executable = getExecutable("yarn", command, "cmd"), - ivyDependency = "com.yarnpkg:yarn:$version@tar.gz", - ignoreScripts = ignoreScripts, - yarnLockMismatchReport = yarnLockMismatchReport, - reportNewYarnLock = reportNewYarnLock, - yarnLockAutoReplace = yarnLockAutoReplace, - yarnResolutions = resolutions - ) + return yarnSpec.produceEnv(project.providers).get() } val restoreYarnLockTaskProvider: TaskProvider diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnSetupTask.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnSetupTask.kt index a27d8ca686a43..a2dcaff50290e 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnSetupTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnSetupTask.kt @@ -8,13 +8,14 @@ package org.jetbrains.kotlin.gradle.targets.js.yarn import org.gradle.api.tasks.Internal import org.gradle.work.DisableCachingByDefault import org.jetbrains.kotlin.gradle.targets.js.AbstractSetupTask +import org.jetbrains.kotlin.gradle.utils.getFile import java.io.File +import javax.inject.Inject @DisableCachingByDefault -abstract class YarnSetupTask : AbstractSetupTask() { - @Transient - @Internal - override val settings = project.yarn +abstract class YarnSetupTask @Inject constructor( + settings: YarnRootEnvSpec +) : AbstractSetupTask(settings) { @get:Internal override val artifactPattern: String @@ -31,7 +32,7 @@ abstract class YarnSetupTask : AbstractSetupTask() { override fun extract(archive: File) { fs.copy { it.from(archiveOperations.tarTree(archive)) - it.into(destination.parentFile) + it.into(destinationProvider.getFile().parentFile) it.includeEmptyDirs = false } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnWorkspaces.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnWorkspaces.kt index acc02e342848c..ac48815b8fb2e 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnWorkspaces.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnWorkspaces.kt @@ -17,6 +17,7 @@ class YarnWorkspaces : YarnBasics() { return listOf( nodeJs .rootPackageDir + .getFile() .resolve(NpmProject.PACKAGE_JSON) ) } @@ -63,7 +64,7 @@ class YarnWorkspaces : YarnBasics() { packageManagerEnvironment: YarnEnvironment, cliArgs: List ) { - val nodeJsWorldDir = nodeJs.rootPackageDir + val nodeJsWorldDir = nodeJs.rootPackageDir.getFile() yarnExec( services,