Browse Source

Update gradle plugin: Deprecate experimental configuration for Compose for Web (#4796)

Since 1.6.10 Compose for Web goes to Alpha and experimental
configuration is not needed anymore. We'll configure the web targets by
default when they're added to projects.

## Testing
- I built the plugin to mavenLocal. And used it in a couple of our
samples.
- After gradle sync completes, I observe the Deprecation warning in
build.gradle.kts on `compose.experimental.web` usages (see a screenshot
below)
<img width="1022" alt="Screenshot 2024-05-10 at 15 41 14"
src="https://github.com/JetBrains/compose-multiplatform/assets/7372778/e8ede073-8d34-4dd7-ae74-c83ca0ff5c96">

Then I remove deprecated API usages and test that the project works
without it:
- run `./gradlew clean` just in case
- run the app: `./gradlew wasmJsBrowserRun` and `./gradlew jsBrowserRun`
- both run fine
- build the production distribution: `./gradlew
wasmJsBrowserDistribution`
- `cd ..../build/dist/wasmJs/productionExecutable` and run `python -m
http.server`, open a browser at `http://localhost:8000` - the app should
work the same way it works with gradle tasks above

<!-- Optional -->
This should be tested by QA

## Release Notes

### Highlights - Web
- Compose for Web goes to Alpha!
Some experimental Compose Multiplatform Gradle plugin APIs for web app
configuration were deprecated. Their usage is not required anymore.

(cherry picked from commit 885ea3da2a)
release/1.6.10 v1.6.10-rc02
Oleksandr Karpovich 7 months ago committed by Oleksandr.Karpovich
parent
commit
966b8e5379
  1. 3
      gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/ComposePlugin.kt
  2. 8
      gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/experimental/dsl/ExperimentalExtension.kt
  3. 3
      gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/experimental/dsl/ExperimentalWebApplication.kt
  4. 9
      gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/experimental/dsl/ExperimentalWebExtension.kt
  5. 1
      gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/experimental/internal/checkExperimentalTargets.kt
  6. 24
      gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/experimental/internal/configureExperimental.kt
  7. 48
      gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/experimental/web/tasks/ExperimentalUnpackSkikoWasmRuntimeTask.kt
  8. 10
      gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/web/dsl/WebApplication.kt
  9. 23
      gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/web/internal/configureWebApplication.kt
  10. 50
      gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/web/tasks/UnpackSkikoWasmRuntimeTask.kt

3
gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/ComposePlugin.kt

@ -27,6 +27,7 @@ import org.jetbrains.compose.internal.utils.currentTarget
import org.jetbrains.compose.resources.ResourcesExtension import org.jetbrains.compose.resources.ResourcesExtension
import org.jetbrains.compose.resources.configureComposeResources import org.jetbrains.compose.resources.configureComposeResources
import org.jetbrains.compose.web.WebExtension import org.jetbrains.compose.web.WebExtension
import org.jetbrains.compose.web.internal.configureWeb
import org.jetbrains.kotlin.com.github.gundy.semver4j.SemVer import org.jetbrains.kotlin.com.github.gundy.semver4j.SemVer
import org.jetbrains.kotlin.gradle.dsl.KotlinCompile import org.jetbrains.kotlin.gradle.dsl.KotlinCompile
import org.jetbrains.kotlin.gradle.dsl.KotlinJsCompile import org.jetbrains.kotlin.gradle.dsl.KotlinJsCompile
@ -65,7 +66,7 @@ abstract class ComposePlugin : Plugin<Project> {
project.afterEvaluate { project.afterEvaluate {
configureDesktop(project, desktopExtension) configureDesktop(project, desktopExtension)
project.configureExperimental(composeExtension, experimentalExtension) project.configureWeb(composeExtension)
project.plugins.withId(KOTLIN_MPP_PLUGIN_ID) { project.plugins.withId(KOTLIN_MPP_PLUGIN_ID) {
val mppExt = project.mppExt val mppExt = project.mppExt
project.configureExperimentalTargetsFlagsCheck(mppExt) project.configureExperimentalTargetsFlagsCheck(mppExt)

8
gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/experimental/dsl/ExperimentalExtension.kt

@ -12,7 +12,15 @@ import javax.inject.Inject
abstract class ExperimentalExtension @Inject constructor( abstract class ExperimentalExtension @Inject constructor(
objects: ObjectFactory objects: ObjectFactory
) { ) {
@Deprecated(
message = "Starting from 1.6.10, Compose for Web goes to Alpha. Experimental configuration is not needed anymore.",
)
val web: ExperimentalWebExtension = objects.newInstance(ExperimentalWebExtension::class.java) val web: ExperimentalWebExtension = objects.newInstance(ExperimentalWebExtension::class.java)
@Deprecated(
message = "Starting from 1.6.10, Compose for Web goes to Alpha. Experimental configuration is not needed anymore."
)
fun web(action: Action<ExperimentalWebExtension>) { fun web(action: Action<ExperimentalWebExtension>) {
action.execute(web) action.execute(web)
} }

3
gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/experimental/dsl/ExperimentalWebApplication.kt

@ -7,6 +7,9 @@ package org.jetbrains.compose.experimental.dsl
import javax.inject.Inject import javax.inject.Inject
@Deprecated(
message = "Starting from 1.6.10, Compose for Web goes to Alpha. Experimental configuration is not needed anymore.",
)
abstract class ExperimentalWebApplication @Inject constructor( abstract class ExperimentalWebApplication @Inject constructor(
@Suppress("unused") @Suppress("unused")
val name: String, val name: String,

9
gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/experimental/dsl/ExperimentalWebExtension.kt

@ -10,15 +10,24 @@ import org.gradle.api.model.ObjectFactory
import org.gradle.api.plugins.ExtensionAware import org.gradle.api.plugins.ExtensionAware
import javax.inject.Inject import javax.inject.Inject
@Deprecated(
message = "Starting from 1.6.10, Compose for Web goes to Alpha. Experimental configuration is not needed anymore.",
)
abstract class ExperimentalWebExtension @Inject constructor(private val objectFactory: ObjectFactory) : ExtensionAware { abstract class ExperimentalWebExtension @Inject constructor(private val objectFactory: ObjectFactory) : ExtensionAware {
internal var _isApplicationInitialized = false internal var _isApplicationInitialized = false
private set private set
@Deprecated(
message = "Starting from 1.6.10, Compose for Web goes to Alpha. Experimental configuration is not needed anymore.",
)
val application: ExperimentalWebApplication by lazy { val application: ExperimentalWebApplication by lazy {
_isApplicationInitialized = true _isApplicationInitialized = true
objectFactory.newInstance(ExperimentalWebApplication::class.java, "main") objectFactory.newInstance(ExperimentalWebApplication::class.java, "main")
} }
@Deprecated(
message = "Starting from 1.6.10, Compose for Web goes to Alpha. Experimental configuration is not needed anymore.",
)
fun application(fn: Action<ExperimentalWebApplication>) { fun application(fn: Action<ExperimentalWebApplication>) {
fn.execute(application) fn.execute(application)
} }

1
gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/experimental/internal/checkExperimentalTargets.kt

@ -27,7 +27,6 @@ private val TargetType.gradlePropertyName get() = "org.jetbrains.compose.experim
private val EXPERIMENTAL_TARGETS: Set<TargetType> = setOf( private val EXPERIMENTAL_TARGETS: Set<TargetType> = setOf(
TargetType("macos", presets = listOf("macosX64", "macosArm64")), TargetType("macos", presets = listOf("macosX64", "macosArm64")),
TargetType("jscanvas", presets = listOf("jsIr", "js")), TargetType("jscanvas", presets = listOf("jsIr", "js")),
TargetType("wasm", presets = listOf("wasm", "wasmJs")),
) )
private sealed interface CheckResult { private sealed interface CheckResult {

24
gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/experimental/internal/configureExperimental.kt

@ -1,24 +0,0 @@
/*
* Copyright 2020-2021 JetBrains s.r.o. and respective authors and developers.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file.
*/
package org.jetbrains.compose.experimental.internal
import org.gradle.api.Project
import org.jetbrains.compose.ComposeExtension
import org.jetbrains.compose.experimental.dsl.ExperimentalExtension
import org.jetbrains.compose.experimental.web.internal.configureExperimentalWebApplication
import org.jetbrains.compose.web.WebExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
internal fun Project.configureExperimental(
composeExt: ComposeExtension,
experimentalExt: ExperimentalExtension
) {
if (experimentalExt.web._isApplicationInitialized) {
val webExt = composeExt.extensions.getByType(WebExtension::class.java)
webExt.targetsToConfigure(project)
.configureExperimentalWebApplication(project, experimentalExt.web.application)
}
}

48
gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/experimental/web/tasks/ExperimentalUnpackSkikoWasmRuntimeTask.kt

@ -5,46 +5,10 @@
package org.jetbrains.compose.experimental.web.tasks package org.jetbrains.compose.experimental.web.tasks
import org.gradle.api.DefaultTask import org.jetbrains.compose.web.tasks.UnpackSkikoWasmRuntimeTask
import org.gradle.api.file.ArchiveOperations
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.file.FileCollection
import org.gradle.api.file.FileSystemOperations
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.OutputDirectory
import org.gradle.api.tasks.TaskAction
import org.jetbrains.compose.internal.utils.clearDirs
import java.io.File
import javax.inject.Inject
abstract class ExperimentalUnpackSkikoWasmRuntimeTask : DefaultTask() { @Deprecated(
@get:InputFiles message = "Starting from 1.6.10 Compose for Web goes to Alpha",
lateinit var skikoRuntimeFiles: FileCollection replaceWith = ReplaceWith("UnpackSkikoWasmRuntimeTask")
)
@get:OutputDirectory abstract class ExperimentalUnpackSkikoWasmRuntimeTask : UnpackSkikoWasmRuntimeTask()
abstract val outputDir: DirectoryProperty
@get:Inject
internal abstract val archiveOperations: ArchiveOperations
@get:Inject
internal abstract val fileOperations: FileSystemOperations
@TaskAction
fun run() {
fileOperations.clearDirs(outputDir)
for (file in skikoRuntimeFiles.files) {
if (file.name.endsWith(".jar", ignoreCase = true)) {
unpackJar(file)
}
}
}
private fun unpackJar(file: File) {
fileOperations.copy { copySpec ->
copySpec.from(archiveOperations.zipTree(file))
copySpec.into(outputDir)
}
}
}

10
gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/web/dsl/WebApplication.kt

@ -0,0 +1,10 @@
package org.jetbrains.compose.web.dsl
import javax.inject.Inject
abstract class WebApplication @Inject constructor(
@Suppress("unused")
val name: String,
) {
}

23
gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/experimental/web/internal/configureExperimentalWebApplication.kt → gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/web/internal/configureWebApplication.kt

@ -3,7 +3,7 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file.
*/ */
package org.jetbrains.compose.experimental.web.internal package org.jetbrains.compose.web.internal
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.Configuration
@ -11,16 +11,25 @@ import org.gradle.api.artifacts.ResolvedDependency
import org.gradle.api.artifacts.UnresolvedDependency import org.gradle.api.artifacts.UnresolvedDependency
import org.gradle.api.provider.Provider import org.gradle.api.provider.Provider
import org.jetbrains.compose.ComposeBuildConfig import org.jetbrains.compose.ComposeBuildConfig
import org.jetbrains.compose.experimental.dsl.ExperimentalWebApplication import org.jetbrains.compose.ComposeExtension
import org.jetbrains.compose.experimental.web.tasks.ExperimentalUnpackSkikoWasmRuntimeTask import org.jetbrains.compose.web.tasks.UnpackSkikoWasmRuntimeTask
import org.jetbrains.compose.internal.utils.* import org.jetbrains.compose.internal.utils.*
import org.jetbrains.compose.internal.utils.registerTask import org.jetbrains.compose.internal.utils.registerTask
import org.jetbrains.compose.internal.utils.uppercaseFirstChar import org.jetbrains.compose.internal.utils.uppercaseFirstChar
import org.jetbrains.compose.web.WebExtension
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTarget import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTarget
internal fun Collection<KotlinJsIrTarget>.configureExperimentalWebApplication( internal fun Project.configureWeb(
project: Project, composeExt: ComposeExtension,
app: ExperimentalWebApplication ) {
val webExt = composeExt.extensions.getByType(WebExtension::class.java)
// configure only if there is k/wasm or k/js target:
webExt.targetsToConfigure(project)
.configureWebApplication(project)
}
internal fun Collection<KotlinJsIrTarget>.configureWebApplication(
project: Project
) { ) {
val skikoJsWasmRuntimeConfiguration = project.configurations.create("COMPOSE_SKIKO_JS_WASM_RUNTIME") val skikoJsWasmRuntimeConfiguration = project.configurations.create("COMPOSE_SKIKO_JS_WASM_RUNTIME")
val skikoJsWasmRuntimeDependency = skikoVersionProvider(project).map { skikoVersion -> val skikoJsWasmRuntimeDependency = skikoVersionProvider(project).map { skikoVersion ->
@ -37,7 +46,7 @@ internal fun Collection<KotlinJsIrTarget>.configureExperimentalWebApplication(
mainCompilation.defaultSourceSet.resources.srcDir(unpackedRuntimeDir) mainCompilation.defaultSourceSet.resources.srcDir(unpackedRuntimeDir)
testCompilation.defaultSourceSet.resources.srcDir(unpackedRuntimeDir) testCompilation.defaultSourceSet.resources.srcDir(unpackedRuntimeDir)
val unpackRuntime = project.registerTask<ExperimentalUnpackSkikoWasmRuntimeTask>(taskName) { val unpackRuntime = project.registerTask<UnpackSkikoWasmRuntimeTask>(taskName) {
skikoRuntimeFiles = skikoJsWasmRuntimeConfiguration skikoRuntimeFiles = skikoJsWasmRuntimeConfiguration
outputDir.set(unpackedRuntimeDir) outputDir.set(unpackedRuntimeDir)
} }

50
gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/web/tasks/UnpackSkikoWasmRuntimeTask.kt

@ -0,0 +1,50 @@
/*
* Copyright 2020-2022 JetBrains s.r.o. and respective authors and developers.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file.
*/
package org.jetbrains.compose.web.tasks
import org.gradle.api.DefaultTask
import org.gradle.api.file.ArchiveOperations
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.file.FileCollection
import org.gradle.api.file.FileSystemOperations
import org.gradle.api.tasks.InputFiles
import org.gradle.api.tasks.OutputDirectory
import org.gradle.api.tasks.TaskAction
import org.jetbrains.compose.internal.utils.clearDirs
import java.io.File
import javax.inject.Inject
abstract class UnpackSkikoWasmRuntimeTask : DefaultTask() {
@get:InputFiles
lateinit var skikoRuntimeFiles: FileCollection
@get:OutputDirectory
abstract val outputDir: DirectoryProperty
@get:Inject
internal abstract val archiveOperations: ArchiveOperations
@get:Inject
internal abstract val fileOperations: FileSystemOperations
@TaskAction
fun run() {
fileOperations.clearDirs(outputDir)
for (file in skikoRuntimeFiles.files) {
if (file.name.endsWith(".jar", ignoreCase = true)) {
unpackJar(file)
}
}
}
private fun unpackJar(file: File) {
fileOperations.copy { copySpec ->
copySpec.from(archiveOperations.zipTree(file))
copySpec.into(outputDir)
}
}
}
Loading…
Cancel
Save