Skip to content

Commit

Permalink
[Wasm] Setup and configure binaryen per project
Browse files Browse the repository at this point in the history
^KT-74840 fixed
  • Loading branch information
ilgonmic authored and Space Team committed Feb 13, 2025
1 parent b63b53f commit 958579f
Show file tree
Hide file tree
Showing 15 changed files with 223 additions and 137 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
package org.jetbrains.kotlin.gradle

import org.gradle.util.GradleVersion
import org.jetbrains.kotlin.gradle.targets.js.binaryen.BinaryenEnvSpec
import org.jetbrains.kotlin.gradle.targets.js.dsl.Distribution
import org.jetbrains.kotlin.gradle.testbase.*
import org.jetbrains.kotlin.gradle.util.replaceText
Expand Down Expand Up @@ -437,4 +438,31 @@ class KotlinWasmGradlePluginIT : KGPBaseTest() {
build("help")
}
}

@OptIn(ExperimentalWasmDsl::class)
@DisplayName("Different binaryen versions per project")
@GradleTest
fun testDifferentBinaryenVersions(gradleVersion: GradleVersion) {
project("wasm-browser-several-modules", gradleVersion) {
subProject("foo").let {
it.buildScriptInjection {
project.extensions.getByType(BinaryenEnvSpec::class.java).version.set("119")
}
}

subProject("bar").let {
it.buildScriptInjection {
project.extensions.getByType(BinaryenEnvSpec::class.java).version.set("118")
}
}

build(":foo:compileProductionExecutableKotlinWasmJsOptimize") {
assertOutputContains("binaryen-version_119/bin/wasm-opt")
}

build(":bar:compileProductionExecutableKotlinWasmJsOptimize") {
assertOutputContains("binaryen-version_118/bin/wasm-opt")
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
plugins {
id("org.jetbrains.kotlin.multiplatform")
}


kotlin {
wasmJs {
binaries.executable()
browser {
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* Copyright 2010-2023 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, world")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
plugins {
id("org.jetbrains.kotlin.multiplatform")
}


kotlin {
wasmJs {
binaries.executable()
browser {
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* Copyright 2010-2023 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, world")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
include("foo")
include("bar")
Original file line number Diff line number Diff line change
Expand Up @@ -3155,6 +3155,17 @@ public final class org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenEnv :
public fun toString ()Ljava/lang/String;
}

public abstract class org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenEnvSpec : org/jetbrains/kotlin/gradle/targets/js/EnvSpec {
public static final field Companion Lorg/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenEnvSpec$Companion;
public static final field EXTENSION_NAME Ljava/lang/String;
public fun <init> ()V
public fun getExecutable ()Lorg/gradle/api/provider/Provider;
protected final fun produceEnv ()Lorg/gradle/api/provider/Provider;
}

public final class org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenEnvSpec$Companion {
}

public abstract class org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenExec : org/gradle/api/tasks/AbstractExecTask {
public static final field Companion Lorg/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenExec$Companion;
public fun <init> ()V
Expand All @@ -3175,41 +3186,35 @@ public final class org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenExec$
public static synthetic fun register$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 <init> ()V
public fun getExecutable ()Lorg/gradle/api/provider/Provider;
protected final fun produceEnv ()Lorg/gradle/api/provider/Provider;
}

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 class org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenExtension : org/jetbrains/kotlin/gradle/targets/js/AbstractSettings {
public static final field Companion Lorg/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenExtension$Companion;
public static final field EXTENSION_NAME Ljava/lang/String;
public fun <init> (Lorg/gradle/api/Project;Lorg/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenRootEnvSpec;)V
public fun <init> (Lorg/gradle/api/Project;Lorg/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenEnvSpec;)V
public synthetic fun finalizeConfiguration ()Ljava/lang/Object;
protected fun finalizeConfiguration ()Lorg/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenEnv;
public final fun getRootProject ()Lorg/gradle/api/Project;
public final fun getSetupTaskProvider ()Lorg/gradle/api/tasks/TaskProvider;
}

public final class org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenRootExtension$Companion {
public final class org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenExtension$Companion {
}

public class org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenRootPlugin : org/gradle/api/Plugin {
public static final field Companion Lorg/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenRootPlugin$Companion;
public abstract class org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenPlugin : org/gradle/api/Plugin {
public static final field Companion Lorg/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenPlugin$Companion;
public static final field TASKS_GROUP_NAME Ljava/lang/String;
public fun <init> ()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/binaryen/BinaryenRootPlugin$Companion {
public final fun apply (Lorg/gradle/api/Project;)Lorg/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenRootExtension;
public final fun getKotlinBinaryenExtension (Lorg/gradle/api/Project;)Lorg/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenRootExtension;
public final class org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenPlugin$Companion {
public final fun apply (Lorg/gradle/api/Project;)Lorg/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenExtension;
public final fun getKotlinBinaryenExtension (Lorg/gradle/api/Project;)Lorg/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenExtension;
}

public class org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenRootPlugin : org/gradle/api/Plugin {
public fun <init> ()V
public synthetic fun apply (Ljava/lang/Object;)V
public fun apply (Lorg/gradle/api/Project;)V
}

public abstract class org/jetbrains/kotlin/gradle/targets/js/binaryen/BinaryenSetupTask : org/jetbrains/kotlin/gradle/targets/js/AbstractSetupTask {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import org.jetbrains.kotlin.gradle.utils.getFile
* Specification for executing Binaryen, an optimization tool for wasm files.
*/
@ExperimentalWasmDsl
abstract class BinaryenRootEnvSpec : EnvSpec<BinaryenEnv>() {
abstract class BinaryenEnvSpec : EnvSpec<BinaryenEnv>() {

/**
* Specify Binaryen platform information, with name and architecture.
Expand Down Expand Up @@ -67,3 +67,6 @@ abstract class BinaryenRootEnvSpec : EnvSpec<BinaryenEnv>() {
const val EXTENSION_NAME: String = "kotlinBinaryenSpec"
}
}

@OptIn(ExperimentalWasmDsl::class)
typealias BinaryenRootEnvSpec = BinaryenEnvSpec
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ 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.targets.js.nodejs.NodeJsExec
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsExec.Companion
import org.jetbrains.kotlin.gradle.tasks.registerTask
import org.jetbrains.kotlin.gradle.utils.newFileProperty
import org.jetbrains.kotlin.platform.wasm.BinaryenConfig
Expand Down Expand Up @@ -76,7 +75,7 @@ constructor() : AbstractExecTask<BinaryenExec>(BinaryenExec::class.java) {
): TaskProvider<BinaryenExec> {
val target = compilation.target
val project = target.project
val binaryen = BinaryenRootPlugin.apply(project.rootProject)
val binaryen = BinaryenPlugin.apply(project)
return project.registerTask(
name,
) {
Expand All @@ -87,14 +86,15 @@ constructor() : AbstractExecTask<BinaryenExec>(BinaryenExec::class.java) {
}
}

@ExperimentalWasmDsl
@Deprecated(
"Use register instead",
ReplaceWith("register(compilation, name, configuration)")
)
fun create(
compilation: KotlinJsIrCompilation,
name: String,
configuration: NodeJsExec.() -> Unit = {},
): TaskProvider<NodeJsExec> = NodeJsExec.register(compilation, name, configuration)
configuration: BinaryenExec.() -> Unit = {},
): TaskProvider<BinaryenExec> = register(compilation, name, configuration)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,10 @@ import org.jetbrains.kotlin.gradle.targets.js.AbstractSettings
import org.jetbrains.kotlin.gradle.utils.property

@OptIn(ExperimentalWasmDsl::class)
open class BinaryenRootExtension(
open class BinaryenExtension(
@Transient val rootProject: Project,
private val binaryenSpec: BinaryenRootEnvSpec,
private val binaryenSpec: BinaryenEnvSpec,
) : AbstractSettings<BinaryenEnv>() {
init {
check(rootProject.rootProject == rootProject)
}

private val gradleHome = rootProject.gradle.gradleUserHomeDir.also {
rootProject.logger.kotlinInfo("Storing cached files in $it")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* 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.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
import org.jetbrains.kotlin.gradle.targets.js.binaryen.BinaryenExtension.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.util.capitalizeDecapitalize.toLowerCaseAsciiOnly

@OptIn(ExperimentalWasmDsl::class)
abstract class BinaryenPlugin internal constructor() : Plugin<Project> {
override fun apply(project: Project) {
MultiplePluginDeclarationDetector.detect(project)

project.plugins.apply(BasePlugin::class.java)

val spec = project.extensions.createBinaryenEnvSpec()

val settings = project.extensions.create(
EXTENSION_NAME,
BinaryenExtension::class.java,
project,
spec
)

spec.initializeBinaryenRootEnvSpec(settings)

addPlatform(project, settings)

project.registerTask<BinaryenSetupTask>(BinaryenSetupTask.NAME, listOf(spec)) {
it.group = TASKS_GROUP_NAME
it.description = "Download and install a binaryen"
it.configuration = it.ivyDependencyProvider.map { ivyDependency ->
project.configurations.detachedConfiguration(project.dependencies.create(ivyDependency))
.also { conf -> conf.isTransitive = false }
}
}

project.registerTask<CleanDataTask>("binaryen" + CleanDataTask.NAME_SUFFIX) {
it.cleanableStoreProvider = project.provider { settings.requireConfigured().cleanableStore }
it.group = TASKS_GROUP_NAME
it.description = "Clean unused local binaryen version"
}
}

private fun ExtensionContainer.createBinaryenEnvSpec(): BinaryenEnvSpec {
return create(
BinaryenEnvSpec.EXTENSION_NAME,
BinaryenEnvSpec::class.java
)
}

private fun BinaryenEnvSpec.initializeBinaryenRootEnvSpec(
rootBinaryen: BinaryenExtension,
) {
download.convention(rootBinaryen.downloadProperty)
downloadBaseUrl.convention(rootBinaryen.downloadBaseUrlProperty)
allowInsecureProtocol.convention(false)
installationDirectory.convention(rootBinaryen.installationDirectory)
version.convention(rootBinaryen.versionProperty)
command.convention(rootBinaryen.commandProperty)
platform.convention(rootBinaryen.platform)
}

private fun addPlatform(project: Project, extension: BinaryenExtension) {
val uname = project.providers.unameExecResult

extension.platform.value(
project.providers.systemProperty("os.name")
.zip(
project.providers.systemProperty("os.arch")
) { name, arch ->
parseBinaryenPlatform(name.toLowerCaseAsciiOnly(), arch, uname)
}
).disallowChanges()
}

companion object {
const val TASKS_GROUP_NAME: String = "binaryen"

fun apply(project: Project): BinaryenExtension {
project.plugins.apply(BinaryenPlugin::class.java)
return project.extensions.getByName(EXTENSION_NAME) as BinaryenExtension
}

val Project.kotlinBinaryenExtension: BinaryenExtension
get() = extensions.getByName(EXTENSION_NAME).castIsolatedKotlinPluginClassLoaderAware()
}
}
Loading

0 comments on commit 958579f

Please sign in to comment.