From bc02ee8355796cf0cfa41b8ab4ab7da465dc069c Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Wed, 18 Sep 2024 10:02:52 +0000 Subject: [PATCH] [Wasm] Move nodejs setup task to project-scoped plugin NodeJsPlugin To solve problem that users cannot set Node.JS version per sub-project, new plugin NodeJsPlugin is introduced and it now registers setup task per-project NodeJsRootExtension has deprecated properties to configure Node.JS version, But it influences only rootProject's NodeJs Added new kind of extensions to configure tools (Binaryen, D8, Node.js, Yarn) with Provider API. In the future old extensions should be deprecated and removed, and new "EnvSpec" should be the only way to configure ^KT-69628 fixed Co-authored-by: Adam Semenenko --- .../kotlin/gradle/ExperimentalWasmDsl.kt | 2 +- .../kotlin/gradle/NodeJsGradlePluginIT.kt | 88 +++++++ .../app/build.gradle.kts | 31 +-- .../kotlin-js-dce/mainProject/build.gradle | 41 ++-- .../new-mpp-wasm-test/build.gradle.kts | 2 +- .../build.gradle.kts | 4 +- .../new-mpp-wasm-wasi-test/build.gradle.kts | 2 +- .../app1/build.gradle.kts | 14 ++ .../app1/src/jsMain/kotlin/main.kt | 10 + .../app2/build.gradle.kts | 14 ++ .../app2/src/jsMain/kotlin/foo.kt | 10 + .../subprojects-nodejs-setup/build.gradle.kts | 3 + .../settings.gradle.kts | 2 + .../build.gradle.kts | 4 +- .../api/all/kotlin-gradle-plugin.api | 232 ++++++++++-------- .../gradle/targets/js/AbstractEnvSpec.kt | 47 ++++ .../gradle/targets/js/AbstractSettings.kt | 49 +++- .../gradle/targets/js/AbstractSetupTask.kt | 64 +++-- .../targets/js/binaryen/BinaryenExec.kt | 2 + .../js/binaryen/BinaryenRootEnvSpec.kt | 64 +++++ .../js/binaryen/BinaryenRootExtension.kt | 54 ++-- .../targets/js/binaryen/BinaryenRootPlugin.kt | 38 ++- .../targets/js/binaryen/BinaryenSetupTask.kt | 26 +- .../kotlin/gradle/targets/js/d8/D8EnvSpec.kt | 80 ++++++ .../kotlin/gradle/targets/js/d8/D8Exec.kt | 6 +- .../gradle/targets/js/d8/D8Extension.kt | 63 +++++ .../kotlin/gradle/targets/js/d8/D8Plugin.kt | 86 +++++++ .../gradle/targets/js/d8/D8RootExtension.kt | 79 +----- .../gradle/targets/js/d8/D8RootPlugin.kt | 58 +---- .../gradle/targets/js/d8/D8SetupTask.kt | 23 +- .../targets/js/dsl/KotlinWasmJsTargetDsl.kt | 2 + .../kotlin/gradle/targets/js/ir/JsBinaries.kt | 2 + .../gradle/targets/js/ir/KotlinBrowserJsIr.kt | 20 +- .../kotlin/gradle/targets/js/ir/KotlinD8Ir.kt | 6 +- .../gradle/targets/js/ir/KotlinJsIrTarget.kt | 5 +- .../gradle/targets/js/ir/KotlinNodeJsIr.kt | 18 +- .../gradle/targets/js/nodejs/NodeJsEnv.kt | 3 - .../gradle/targets/js/nodejs/NodeJsEnvSpec.kt | 72 ++++++ .../gradle/targets/js/nodejs/NodeJsExec.kt | 22 +- .../gradle/targets/js/nodejs/NodeJsPlugin.kt | 86 +++++++ .../targets/js/nodejs/NodeJsRootExtension.kt | 162 +++++------- .../targets/js/nodejs/NodeJsRootPlugin.kt | 85 +++---- .../targets/js/nodejs/NodeJsSetupTask.kt | 21 +- .../kotlin/gradle/targets/js/npm/Npm.kt | 3 +- .../gradle/targets/js/npm/NpmApiExecution.kt | 20 +- .../gradle/targets/js/npm/NpmExtension.kt | 6 +- .../gradle/targets/js/npm/NpmProject.kt | 14 +- .../targets/js/npm/NpmResolverPlugin.kt | 14 +- .../resolver/KotlinCompilationNpmResolver.kt | 4 +- .../js/npm/tasks/KotlinNpmInstallTask.kt | 30 +-- .../js/npm/tasks/KotlinPackageJsonTask.kt | 6 +- .../js/npm/tasks/RootPackageJsonTask.kt | 19 +- .../gradle/targets/js/testing/KotlinJsTest.kt | 11 +- .../gradle/targets/js/testing/KotlinWasmD8.kt | 11 +- .../targets/js/testing/karma/KotlinKarma.kt | 4 +- .../targets/js/testing/mocha/KotlinMocha.kt | 6 +- .../js/typescript/TypeScriptValidationTask.kt | 4 +- .../targets/js/webpack/KotlinWebpack.kt | 4 +- .../gradle/targets/js/yarn/YarnPlugin.kt | 76 ++++-- .../gradle/targets/js/yarn/YarnRootEnvSpec.kt | 106 ++++++++ .../targets/js/yarn/YarnRootExtension.kt | 61 ++--- .../gradle/targets/js/yarn/YarnSetupTask.kt | 11 +- .../gradle/targets/js/yarn/YarnWorkspaces.kt | 3 +- 63 files changed, 1442 insertions(+), 673 deletions(-) create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NodeJsGradlePluginIT.kt create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/subprojects-nodejs-setup/app1/build.gradle.kts create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/subprojects-nodejs-setup/app1/src/jsMain/kotlin/main.kt create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/subprojects-nodejs-setup/app2/build.gradle.kts create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/subprojects-nodejs-setup/app2/src/jsMain/kotlin/foo.kt create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/subprojects-nodejs-setup/build.gradle.kts create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/subprojects-nodejs-setup/settings.gradle.kts create mode 100644 libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/AbstractEnvSpec.kt create mode 100644 libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenRootEnvSpec.kt create mode 100644 libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/d8/D8EnvSpec.kt create mode 100644 libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/d8/D8Extension.kt create mode 100644 libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/d8/D8Plugin.kt create mode 100644 libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsEnvSpec.kt create mode 100644 libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/nodejs/NodeJsPlugin.kt create mode 100644 libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/yarn/YarnRootEnvSpec.kt 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,