Browse Source

Support Kotlin JS targets in Compose Gradle plugin

pull/623/head
Alexey Tsvetkov 4 years ago committed by Alexey Tsvetkov
parent
commit
7a47ba8dd8
  1. 2
      gradle-plugins/buildSrc/src/main/kotlin/BuildProperties.kt
  2. 1
      gradle-plugins/compose/build.gradle.kts
  3. 39
      gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/ComposeCompilerKotlinSupportPlugin.kt
  4. 15
      gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/ComposePlugin.kt
  5. 20
      gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/internal/projectExtensions.kt
  6. 60
      gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/web/WebExtension.kt
  7. 16
      gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/web/internal/configureWeb.kt
  8. 1
      gradle-plugins/gradle.properties

2
gradle-plugins/buildSrc/src/main/kotlin/BuildProperties.kt

@ -17,4 +17,6 @@ object BuildProperties {
fun deployVersion(project: Project): String = fun deployVersion(project: Project): String =
System.getenv("COMPOSE_GRADLE_PLUGIN_VERSION") System.getenv("COMPOSE_GRADLE_PLUGIN_VERSION")
?: project.findProperty("deploy.version") as String ?: project.findProperty("deploy.version") as String
fun isComposeWithWeb(project: Project): Boolean =
project.findProperty("compose.with.web") == "true"
} }

1
gradle-plugins/compose/build.gradle.kts

@ -25,6 +25,7 @@ buildConfig {
packageName = "org.jetbrains.compose" packageName = "org.jetbrains.compose"
clsName = "ComposeBuildConfig" clsName = "ComposeBuildConfig"
buildConfigField("String", "composeVersion", BuildProperties.composeVersion(project)) buildConfigField("String", "composeVersion", BuildProperties.composeVersion(project))
buildConfigField("Boolean", "isComposeWithWeb", BuildProperties.isComposeWithWeb(project).toString())
} }
val embedded by configurations.creating val embedded by configurations.creating

39
gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/ComposeCompilerKotlinSupportPlugin.kt

@ -6,23 +6,48 @@
package org.jetbrains.compose package org.jetbrains.compose
import org.gradle.api.provider.Provider import org.gradle.api.provider.Provider
import org.jetbrains.compose.internal.webExt
import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTarget
class ComposeCompilerKotlinSupportPlugin : KotlinCompilerPluginSupportPlugin { class ComposeCompilerKotlinSupportPlugin : KotlinCompilerPluginSupportPlugin {
override fun getCompilerPluginId(): String = override fun getCompilerPluginId(): String =
"org.jetbrains.compose" "androidx.compose.compiler.plugins.kotlin"
override fun isApplicable(kotlinCompilation: KotlinCompilation<*>): Boolean { override fun isApplicable(kotlinCompilation: KotlinCompilation<*>): Boolean =
val targetPlatform = kotlinCompilation.target.platformType when (kotlinCompilation.target.platformType) {
return targetPlatform != KotlinPlatformType.js KotlinPlatformType.common -> true
&& targetPlatform != KotlinPlatformType.native KotlinPlatformType.jvm -> true
KotlinPlatformType.js -> isApplicableJsTarget(kotlinCompilation.target)
KotlinPlatformType.androidJvm -> true
KotlinPlatformType.native -> false
} }
override fun applyToCompilation(kotlinCompilation: KotlinCompilation<*>): Provider<List<SubpluginOption>> = override fun applyToCompilation(kotlinCompilation: KotlinCompilation<*>): Provider<List<SubpluginOption>> {
kotlinCompilation.target.project.provider { emptyList() } val target = kotlinCompilation.target
return target.project.provider {
platformPluginOptions[target.platformType] ?: emptyList()
}
}
override fun getPluginArtifact(): SubpluginArtifact = override fun getPluginArtifact(): SubpluginArtifact =
SubpluginArtifact( SubpluginArtifact(
groupId = "org.jetbrains.compose.compiler", artifactId = "compiler", version = composeVersion groupId = "org.jetbrains.compose.compiler", artifactId = "compiler", version = composeVersion
) )
private fun isApplicableJsTarget(kotlinTarget: KotlinTarget): Boolean {
if (kotlinTarget !is KotlinJsIrTarget) return false
val project = kotlinTarget.project
val webExt = project.webExt ?: return false
return kotlinTarget in webExt.targetsToConfigure(project)
}
private val platformPluginOptions = mapOf(
KotlinPlatformType.js to options("generateDecoys" to "true")
)
private fun options(vararg options: Pair<String, String>): List<SubpluginOption> =
options.map { SubpluginOption(it.first, it.second) }
} }

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

@ -16,6 +16,7 @@ import org.jetbrains.compose.desktop.DesktopExtension
import org.jetbrains.compose.desktop.application.internal.configureApplicationImpl import org.jetbrains.compose.desktop.application.internal.configureApplicationImpl
import org.jetbrains.compose.desktop.application.internal.currentTarget import org.jetbrains.compose.desktop.application.internal.currentTarget
import org.jetbrains.compose.desktop.preview.internal.initializePreview import org.jetbrains.compose.desktop.preview.internal.initializePreview
import org.jetbrains.compose.web.internal.initializeWeb
import org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler import org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
@ -37,8 +38,11 @@ class ComposePlugin : Plugin<Project> {
} }
project.initializePreview() project.initializePreview()
if (ComposeBuildConfig.isComposeWithWeb) {
project.initializeWeb(composeExtension)
}
project.pluginManager.apply(ComposeCompilerKotlinSupportPlugin::class.java) project.plugins.apply(ComposeCompilerKotlinSupportPlugin::class.java)
project.afterEvaluate { project.afterEvaluate {
if (desktopExtension._isApplicationInitialized) { if (desktopExtension._isApplicationInitialized) {
@ -112,6 +116,9 @@ class ComposePlugin : Plugin<Project> {
val runtime get() = composeDependency("org.jetbrains.compose.runtime:runtime") val runtime get() = composeDependency("org.jetbrains.compose.runtime:runtime")
val ui get() = composeDependency("org.jetbrains.compose.ui:ui") val ui get() = composeDependency("org.jetbrains.compose.ui:ui")
val materialIconsExtended get() = composeDependency("org.jetbrains.compose.material:material-icons-extended") val materialIconsExtended get() = composeDependency("org.jetbrains.compose.material:material-icons-extended")
val web: WebDependencies =
if (ComposeBuildConfig.isComposeWithWeb) WebDependencies
else error("This version of Compose plugin does not support 'compose.web.*' dependencies")
} }
object DesktopDependencies { object DesktopDependencies {
@ -141,6 +148,12 @@ class ComposePlugin : Plugin<Project> {
composeDependency("org.jetbrains.compose.desktop:desktop-jvm-${currentTarget.id}") composeDependency("org.jetbrains.compose.desktop:desktop-jvm-${currentTarget.id}")
} }
} }
object WebDependencies {
val web by lazy {
composeDependency("org.jetbrains.compose.web:web")
}
}
} }
fun KotlinDependencyHandler.compose(groupWithArtifact: String) = composeDependency(groupWithArtifact) fun KotlinDependencyHandler.compose(groupWithArtifact: String) = composeDependency(groupWithArtifact)

20
gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/internal/projectExtensions.kt

@ -0,0 +1,20 @@
/*
* 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.internal
import org.gradle.api.Project
import org.jetbrains.compose.ComposeExtension
import org.jetbrains.compose.web.WebExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
internal val Project.composeExt: ComposeExtension?
get() = extensions.findByType(ComposeExtension::class.java)
internal val Project.webExt: WebExtension?
get() = composeExt?.extensions?.findByType(WebExtension::class.java)
internal val Project.mppExt: KotlinMultiplatformExtension?
get() = extensions.findByType(KotlinMultiplatformExtension::class.java)

60
gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/web/WebExtension.kt

@ -0,0 +1,60 @@
/*
* 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.web
import org.gradle.api.Project
import org.gradle.api.plugins.ExtensionAware
import org.jetbrains.compose.internal.mppExt
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTarget
abstract class WebExtension : ExtensionAware {
private var requestedTargets: Set<KotlinJsIrTarget>? = null
private var targetsToConfigure: Set<KotlinJsIrTarget>? = null
// public api
@Suppress("unused")
fun targets(vararg targets: KotlinTarget) {
check(requestedTargets == null) {
"compose.web.targets() was already set!"
}
val jsIrTargets = linkedSetOf<KotlinJsIrTarget>()
for (target in targets) {
check(target is KotlinJsIrTarget) {
"""|'${target.name}' is not a JS(IR) target:
|* add `kotlin.js.compiler=ir` to gradle properties;
|* define target as `kotlin { js(IR) { ... } }`
""".trimMargin()
}
jsIrTargets.add(target)
}
requestedTargets = jsIrTargets
}
internal fun targetsToConfigure(project: Project): Set<KotlinJsIrTarget> {
targetsToConfigure =
targetsToConfigure
?: requestedTargets
?: defaultJsTargetsToConfigure(project)
return targetsToConfigure!!
}
private fun defaultJsTargetsToConfigure(project: Project): Set<KotlinJsIrTarget> {
val mppTargets = project.mppExt?.targets?.asMap?.values ?: emptySet()
val jsIRTargets = mppTargets.filterIsInstanceTo(LinkedHashSet<KotlinJsIrTarget>())
return if (jsIRTargets.size > 1) {
project.logger.error(
"w: Default configuration for Compose Web is disabled: " +
"multiple Kotlin JS IR targets are defined. " +
"Specify Compose Web Kotlin targets by using `compose.web.targets()`"
)
emptySet()
} else jsIRTargets
}
}

16
gradle-plugins/compose/src/main/kotlin/org/jetbrains/compose/web/internal/configureWeb.kt

@ -0,0 +1,16 @@
/*
* 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.web.internal
import org.gradle.api.Project
import org.jetbrains.compose.ComposeExtension
import org.jetbrains.compose.web.WebExtension
internal fun Project.initializeWeb(composeExtension: ComposeExtension) {
project.plugins.withId("org.jetbrains.kotlin.multiplatform") {
composeExtension.extensions.create("web", WebExtension::class.java)
}
}

1
gradle-plugins/gradle.properties

@ -7,6 +7,7 @@ kotlin.code.style=official
# #
# __LATEST_COMPOSE_RELEASE_VERSION__ # __LATEST_COMPOSE_RELEASE_VERSION__
compose.version=0.4.0-build182 compose.version=0.4.0-build182
compose.with.web=false
# A version of Gradle plugin, that will be published, # A version of Gradle plugin, that will be published,
# unless overridden by COMPOSE_GRADLE_PLUGIN_VERSION env var. # unless overridden by COMPOSE_GRADLE_PLUGIN_VERSION env var.

Loading…
Cancel
Save