From 6ab64e0f7cf86baf5520473eff46f765f572bebd Mon Sep 17 00:00:00 2001 From: "Alexander.Likhachev" Date: Wed, 1 Feb 2023 15:49:20 +0100 Subject: [PATCH] [Gradle, JS] Migrate KotlinWebpack output files configuration to lazy API #KT-56357 Fixed --- .../gradle/targets/js/dsl/Distribution.kt | 9 ++++ .../kotlin/gradle/targets/js/ir/JsBinaries.kt | 7 +-- .../gradle/targets/js/ir/KotlinBrowserJsIr.kt | 20 ++++++-- .../targets/js/ir/KotlinJsBinaryContainer.kt | 3 +- .../js/subtargets/DefaultDistribution.kt | 37 +++++++++++--- .../targets/js/subtargets/KotlinBrowserJs.kt | 22 ++++++-- .../targets/js/webpack/KotlinWebpack.kt | 50 +++++++++---------- 7 files changed, 101 insertions(+), 47 deletions(-) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/dsl/Distribution.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/dsl/Distribution.kt index f5b10e84496..4c108081ac7 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/dsl/Distribution.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/dsl/Distribution.kt @@ -5,9 +5,18 @@ package org.jetbrains.kotlin.gradle.targets.js.dsl +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.provider.Property import java.io.File interface Distribution { + @Deprecated("Use `distributionName` instead", ReplaceWith("distributionName")) var name: String? + + val distributionName: Property + + @Deprecated("Use `outputDirectory` instead", ReplaceWith("outputDirectory")) var directory: File + + val outputDirectory: DirectoryProperty } \ 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 bab18ea1c0a..d9c6995af64 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 @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.gradle.targets.js.dsl.Distribution import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsBinaryMode import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsBinaryContainer.Companion.generateBinaryName import org.jetbrains.kotlin.gradle.targets.js.subtargets.DefaultDistribution +import org.jetbrains.kotlin.gradle.targets.js.subtargets.createDefaultDistribution import org.jetbrains.kotlin.gradle.targets.js.typescript.TypeScriptValidationTask import org.jetbrains.kotlin.gradle.tasks.withType import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName @@ -32,7 +33,7 @@ sealed class JsIrBinary( override val mode: KotlinJsBinaryMode ) : JsBinary { override val distribution: Distribution = - DefaultDistribution(compilation.target.project, name) + createDefaultDistribution(compilation.target.project, name) val linkTaskName: String = linkTaskName() @@ -93,9 +94,9 @@ class Executable( mode ) { override val distribution: Distribution = - DefaultDistribution( + createDefaultDistribution( compilation.target.project, - if (mode == KotlinJsBinaryMode.PRODUCTION) null else super.distribution.name + if (mode == KotlinJsBinaryMode.PRODUCTION) null else super.distribution.distributionName ) val executeTaskBaseName: 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 da194056727..d60c129a01d 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 @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.gradle.targets.js.ir import org.gradle.api.Action import org.gradle.api.Task +import org.gradle.api.provider.Property import org.gradle.api.provider.Provider import org.gradle.api.tasks.Copy import org.gradle.language.base.plugins.LifecycleBasePlugin @@ -14,6 +15,8 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinJsDce import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation +import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.archivesName +import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.distsDirectory import org.jetbrains.kotlin.gradle.report.BuildMetricsService import org.jetbrains.kotlin.gradle.targets.js.addWasmExperimentalArguments import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalDceDsl @@ -114,6 +117,8 @@ abstract class KotlinBrowserJsIr @Inject constructor(target: KotlinJsIrTarget) : binary as Executable val mode = binary.mode + val distsDirectory = project.distsDirectory + val archivesName = project.archivesName val runTask = registerSubTargetTask( disambiguateCamelCased( @@ -123,6 +128,7 @@ abstract class KotlinBrowserJsIr @Inject constructor(target: KotlinJsIrTarget) : listOf(compilation) ) { task -> task.dependsOn(binary.linkSyncTask) + task.outputDirectory.convention(distsDirectory).finalizeValueOnRead() webpackMajorVersion.choose( { task.args.add(0, "serve") }, @@ -179,7 +185,8 @@ abstract class KotlinBrowserJsIr @Inject constructor(target: KotlinJsIrTarget) : inputFilesDirectory = binary.linkSyncTask.map { it.destinationDir }, entryModuleName = binary.linkTask.flatMap { it.compilerOptions.moduleName }, configurationActions = runTaskConfigurations, - nodeJs = nodeJs + nodeJs = nodeJs, + defaultArchivesName = archivesName, ) } @@ -206,6 +213,7 @@ abstract class KotlinBrowserJsIr @Inject constructor(target: KotlinJsIrTarget) : binary as Executable val mode = binary.mode + val archivesName = project.archivesName val distributeResourcesTask = registerSubTargetTask( disambiguateCamelCased( @@ -225,7 +233,7 @@ abstract class KotlinBrowserJsIr @Inject constructor(target: KotlinJsIrTarget) : listOf(compilation) ) { task -> task.description = "build webpack ${mode.name.toLowerCaseAsciiOnly()} bundle" - task._destinationDirectory = binary.distribution.directory + task.outputDirectory.fileValue(binary.distribution.directory).finalizeValueOnRead() BuildMetricsService.registerIfAbsent(project)?.let { task.buildMetricsService.value(it) @@ -243,7 +251,8 @@ abstract class KotlinBrowserJsIr @Inject constructor(target: KotlinJsIrTarget) : inputFilesDirectory = binary.linkSyncTask.map { it.destinationDir }, entryModuleName = binary.linkTask.flatMap { it.compilerOptions.moduleName }, configurationActions = webpackTaskConfigurations, - nodeJs = nodeJs + nodeJs = nodeJs, + defaultArchivesName = archivesName, ) } @@ -276,7 +285,8 @@ abstract class KotlinBrowserJsIr @Inject constructor(target: KotlinJsIrTarget) : inputFilesDirectory: Provider, entryModuleName: Provider, configurationActions: List>, - nodeJs: NodeJsRootExtension + nodeJs: NodeJsRootExtension, + defaultArchivesName: Property, ) { dependsOn( nodeJs.npmInstallTaskProvider, @@ -290,6 +300,8 @@ abstract class KotlinBrowserJsIr @Inject constructor(target: KotlinJsIrTarget) : this.entryModuleName.set(entryModuleName) + mainOutputFileName.convention(defaultArchivesName.orElse("main").map { "$it.js" }).finalizeValueOnRead() + configurationActions.forEach { configure -> configure.execute(this) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsBinaryContainer.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsBinaryContainer.kt index 948ff905e6b..479784e50bc 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsBinaryContainer.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/ir/KotlinJsBinaryContainer.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsBinaryMode.DEVELOPMENT import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsBinaryMode.PRODUCTION import org.jetbrains.kotlin.gradle.targets.js.subtargets.DefaultDistribution import org.jetbrains.kotlin.gradle.targets.js.subtargets.KotlinJsSubTarget +import org.jetbrains.kotlin.gradle.targets.js.subtargets.createDefaultDistribution import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly import javax.inject.Inject @@ -116,7 +117,7 @@ constructor( override val compilation: KotlinJsCompilation = jsCompilation override val name: String = name override val mode: KotlinJsBinaryMode = type - override val distribution: Distribution = DefaultDistribution(jsCompilation.target.project) + override val distribution: Distribution = createDefaultDistribution(jsCompilation.target.project) } } ) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/subtargets/DefaultDistribution.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/subtargets/DefaultDistribution.kt index 79d5258a5c3..597808a81b7 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/subtargets/DefaultDistribution.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/subtargets/DefaultDistribution.kt @@ -6,21 +6,42 @@ package org.jetbrains.kotlin.gradle.targets.js.subtargets import org.gradle.api.Project +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.provider.Property import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.distsDirectory import org.jetbrains.kotlin.gradle.targets.js.dsl.Distribution import org.jetbrains.kotlin.gradle.utils.property import java.io.File +internal fun createDefaultDistribution(project: Project, name: String? = null) = + DefaultDistribution(project, project.objects.property(name)) + +internal fun createDefaultDistribution(project: Project, name: Property?) = + DefaultDistribution(project, project.objects.property().apply { + if (name != null) { + value(name) + } + }) + class DefaultDistribution( private val project: Project, - override var name: String? = null + override val distributionName: Property, ) : Distribution { + @Deprecated("Use `distributionName` instead", ReplaceWith("distributionName")) + override var name: String? + get() = distributionName.orNull + set(value) { + distributionName.set(value) + } - override var directory: File by property { - project.buildDir - .let { buildDir -> - name?.let { buildDir.resolve(it) } - ?: project.distsDirectory.asFile.get() - } - } + @Deprecated("Use `outputDirectory` instead", ReplaceWith("outputDirectory")) + override var directory: File + get() = outputDirectory.get().asFile + set(value) { + outputDirectory.set(value) + } + + override val outputDirectory: DirectoryProperty = project.objects.directoryProperty().convention( + distributionName.flatMap { project.layout.buildDirectory.dir(it) }.orElse(project.distsDirectory) + ) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/subtargets/KotlinBrowserJs.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/subtargets/KotlinBrowserJs.kt index 4fa9f1416ab..5ed78f2bdb9 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/subtargets/KotlinBrowserJs.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/js/subtargets/KotlinBrowserJs.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.gradle.targets.js.subtargets import org.gradle.api.Action import org.gradle.api.Task +import org.gradle.api.provider.Property import org.gradle.api.tasks.Copy import org.gradle.api.tasks.TaskProvider import org.gradle.language.base.plugins.LifecycleBasePlugin @@ -17,6 +18,8 @@ import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation import org.jetbrains.kotlin.gradle.plugin.mpp.isMain import org.jetbrains.kotlin.gradle.plugin.mpp.isTest +import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.archivesName +import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.distsDirectory import org.jetbrains.kotlin.gradle.report.BuildMetricsService import org.jetbrains.kotlin.gradle.targets.js.KotlinJsTarget import org.jetbrains.kotlin.gradle.targets.js.dsl.* @@ -47,7 +50,7 @@ abstract class KotlinBrowserJs @Inject constructor(target: KotlinJsTarget) : private val webpackTaskConfigurations: MutableList> = mutableListOf() private val runTaskConfigurations: MutableList> = mutableListOf() private val dceConfigurations: MutableList> = mutableListOf() - private val distribution: Distribution = DefaultDistribution(project) + private val distribution: Distribution = createDefaultDistribution(project) private val propertiesProvider = PropertiesProvider(project) private val webpackMajorVersion get() = propertiesProvider.webpackMajorVersion @@ -142,6 +145,8 @@ abstract class KotlinBrowserJs @Inject constructor(target: KotlinJsTarget) : compilation.binaries .all { binary -> val type = binary.mode + val distsDirectory = project.distsDirectory + val archivesName = project.archivesName val runTask = registerSubTargetTask( disambiguateCamelCased( @@ -150,6 +155,7 @@ abstract class KotlinBrowserJs @Inject constructor(target: KotlinJsTarget) : ), listOf(compilation) ) { task -> + task.outputDirectory.convention(distsDirectory).finalizeValueOnRead() webpackMajorVersion.choose( { task.args.add(0, "serve") }, { task.bin = "webpack-dev-server/bin/webpack-dev-server.js" } @@ -186,7 +192,8 @@ abstract class KotlinBrowserJs @Inject constructor(target: KotlinJsTarget) : devDceTaskProvider = devDceTaskProvider, mode = type, configurationActions = runTaskConfigurations, - nodeJs = nodeJs + nodeJs = nodeJs, + defaultArchivesName = archivesName, ) } @@ -224,6 +231,7 @@ abstract class KotlinBrowserJs @Inject constructor(target: KotlinJsTarget) : compilation.binaries .all { binary -> val type = binary.mode + val archivesName = project.archivesName val webpackTask = registerSubTargetTask( disambiguateCamelCased( @@ -238,7 +246,7 @@ abstract class KotlinBrowserJs @Inject constructor(target: KotlinJsTarget) : ) task.description = "build webpack ${type.name.toLowerCaseAsciiOnly()} bundle" - task._destinationDirectory = distribution.directory + task.outputDirectory.fileValue(distribution.directory).finalizeValueOnRead() BuildMetricsService.registerIfAbsent(project)?.let { task.buildMetricsService.value(it) @@ -250,7 +258,8 @@ abstract class KotlinBrowserJs @Inject constructor(target: KotlinJsTarget) : devDceTaskProvider = devDceTaskProvider, mode = type, configurationActions = webpackTaskConfigurations, - nodeJs = nodeJs + nodeJs = nodeJs, + defaultArchivesName = archivesName, ) } @@ -277,7 +286,8 @@ abstract class KotlinBrowserJs @Inject constructor(target: KotlinJsTarget) : devDceTaskProvider: TaskProvider, mode: KotlinJsBinaryMode, configurationActions: List>, - nodeJs: NodeJsRootExtension + nodeJs: NodeJsRootExtension, + defaultArchivesName: Property, ) { dependsOn( nodeJs.npmInstallTaskProvider, @@ -310,6 +320,8 @@ abstract class KotlinBrowserJs @Inject constructor(target: KotlinJsTarget) : resolveFromModulesFirst = true + mainOutputFileName.convention(defaultArchivesName.orElse("main").map { "$it.js" }).finalizeValueOnRead() + configurationActions.forEach { configure -> configure.execute(this) } 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 e1ff292ef45..01b5c2b9e87 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 @@ -29,7 +29,6 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.archivesName -import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.distsDirectory import org.jetbrains.kotlin.gradle.report.UsesBuildMetricsService import org.jetbrains.kotlin.gradle.targets.js.RequiredKotlinJsDependency import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinWebpackRulesContainer @@ -42,6 +41,7 @@ import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig.Mode import org.jetbrains.kotlin.gradle.utils.getValue import org.jetbrains.kotlin.gradle.utils.injected import org.jetbrains.kotlin.gradle.utils.property +import org.jetbrains.kotlin.gradle.utils.providerWithLazyConvention import java.io.File import javax.inject.Inject @@ -140,36 +140,34 @@ constructor( ) @get:Internal - @Deprecated("use destinationDirectory instead", ReplaceWith("destinationDirectory")) - val outputPath: File - get() = destinationDirectory - - @get:Internal - internal var _destinationDirectory: File? = null - - private val defaultDestinationDirectory by lazy { - project.distsDirectory.asFile.get() - } - - @get:OutputDirectory + @Deprecated("Use `outputDirectory` instead", ReplaceWith("outputDirectory")) var destinationDirectory: File - get() = _destinationDirectory ?: defaultDestinationDirectory + get() = outputDirectory.asFile.get() set(value) { - _destinationDirectory = value + outputDirectory.set(value) } - private val defaultOutputFileName by lazy { - project.archivesName.orNull + ".js" - } + @get:OutputDirectory + abstract val outputDirectory: DirectoryProperty @get:Internal - var outputFileName: String by property { - defaultOutputFileName - } + @Deprecated("Use `mainOutputFileName` instead", ReplaceWith("mainOutputFileName")) + var outputFileName: String + get() = mainOutputFileName.get() + set(value) { + mainOutputFileName.set(value) + } @get:Internal + abstract val mainOutputFileName: Property + + @get:Internal + @Deprecated("Use `mainOutputFile` instead", ReplaceWith("mainOutputFile")) open val outputFile: File - get() = destinationDirectory.resolve(outputFileName) + get() = mainOutputFile.get().asFile + + @get:Internal + val mainOutputFile: Provider = objects.providerWithLazyConvention { outputDirectory.file(mainOutputFileName) }.flatMap { it } private val projectDir = project.projectDir @@ -220,7 +218,7 @@ constructor( } /** - * [forNpmDependencies] is used to avoid querying [destinationDirectory] before task execution. + * [forNpmDependencies] is used to avoid querying [outputDirectory] before task execution. * Otherwise, Gradle will fail the build. */ private fun createWebpackConfig(forNpmDependencies: Boolean = false) = KotlinWebpackConfig( @@ -228,8 +226,8 @@ constructor( mode = mode, entry = if (forNpmDependencies) null else entry.get().asFile, output = output, - outputPath = if (forNpmDependencies) null else destinationDirectory, - outputFileName = outputFileName, + outputPath = if (forNpmDependencies) null else outputDirectory.get().asFile, + outputFileName = mainOutputFileName.get(), configDirectory = configDirectory, rules = rules, devServer = devServer, @@ -298,7 +296,7 @@ constructor( ).execute(services) val buildMetrics = metrics.get() - destinationDirectory.walkTopDown() + outputDirectory.get().asFile.walkTopDown() .filter { it.isFile } .filter { it.extension == "js" } .map { it.length() }