[WASM] Support for mjs universal launcher

This commit is contained in:
Igor Yakovlev
2022-06-03 18:45:40 +02:00
committed by teamcity
parent c8806763fa
commit f996278171
20 changed files with 103 additions and 171 deletions
+2 -35
View File
@@ -1,6 +1,5 @@
import org.jetbrains.kotlin.gradle.dsl.KotlinCompile
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrLink
import java.io.OutputStream
plugins {
`maven-publish`
@@ -77,13 +76,7 @@ val commonTestSources by task<Sync> {
kotlin {
wasm {
nodejs {
testTask {
useMocha {
timeout = "10s"
}
}
}
nodejs()
}
sourceSets {
@@ -144,33 +137,7 @@ val compileTestKotlinWasm by tasks.existing(KotlinCompile::class) {
}
val compileTestDevelopmentExecutableKotlinWasm = tasks.named<KotlinJsIrLink>("compileTestDevelopmentExecutableKotlinWasm") {
(this as KotlinCompile<*>).kotlinOptions.freeCompilerArgs += listOf("-Xwasm-enable-array-range-checks", "-Xwasm-launcher=d8")
}
val runWasmStdLibTestsWithD8 by tasks.registering(Exec::class) {
dependsOn(":js:js.tests:unzipV8")
dependsOn(compileTestDevelopmentExecutableKotlinWasm)
val unzipV8Task = tasks.getByPath(":js:js.tests:unzipV8")
val d8Path = File(unzipV8Task.outputs.files.single(), "d8")
executable = d8Path.toString()
val compiledFile = compileTestDevelopmentExecutableKotlinWasm
.get()
.kotlinOptions
.outputFile
?.let { File(it) }
check(compiledFile != null)
if (System.getenv("TEAMCITY_VERSION") == null) {
standardOutput = object : OutputStream() {
override fun write(b: Int) = Unit
}
errorOutput = standardOutput
}
workingDir = compiledFile.parentFile
args = listOf("--experimental-wasm-gc", "--experimental-wasm-eh", "--module", compiledFile.name)
(this as KotlinCompile<*>).kotlinOptions.freeCompilerArgs += listOf("-Xwasm-enable-array-range-checks")
}
val runtimeElements by configurations.creating {}
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinTargetTestRun
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsSubTargetContainerDsl
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsSubTargetDsl
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinWasmSubTargetContainerDsl
import org.jetbrains.kotlin.gradle.targets.js.testing.KotlinJsTest
import org.jetbrains.kotlin.gradle.testing.KotlinReportAggregatingTestRun
import org.jetbrains.kotlin.gradle.testing.KotlinTaskTestRun
@@ -82,6 +83,7 @@ open class KotlinJsReportAggregatingTestRun(
target.whenBrowserConfigured { doConfigureInChildren(this) }
target.whenNodejsConfigured { doConfigureInChildren(this) }
(target as? KotlinWasmSubTargetContainerDsl)?.whenD8Configured { doConfigureInChildren(this) }
}
override fun filter(configureFilter: Closure<*>) = filter { target.project.configure(this, configureFilter) }
@@ -63,9 +63,6 @@ open class KotlinBrowserJsIr @Inject constructor(target: KotlinJsIrTarget) :
}
}
override val additionalCompilerOption: String?
get() = "-Xwasm-launcher=esm".takeIf { target.platformType == KotlinPlatformType.wasm }
override fun commonWebpackConfig(body: KotlinWebpackConfig.() -> Unit) {
webpackTaskConfigurations.add {
webpackConfigApplier(body)
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.gradle.targets.js.ir
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
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.dsl.KotlinWasmD8Dsl
@@ -34,7 +33,4 @@ open class KotlinD8Ir @Inject constructor(target: KotlinJsIrTarget) :
override fun configureTestDependencies(test: KotlinJsTest) {
test.dependsOn(d8.setupTaskProvider)
}
override val additionalCompilerOption: String?
get() = "-Xwasm-launcher=d8".takeIf { target.platformType == KotlinPlatformType.wasm }
}
@@ -52,6 +52,10 @@ constructor(
(this as KotlinJsIrSubTarget).produceExecutable()
}
target.whenD8Configured {
(this as KotlinJsIrSubTarget).produceExecutable()
}
return compilation.binaries.executableIrInternal(compilation)
}
@@ -106,6 +110,10 @@ constructor(
(this as KotlinJsIrSubTarget).produceLibrary()
}
target.whenD8Configured {
(this as KotlinJsIrSubTarget).produceLibrary()
}
return createBinaries(
compilation = compilation,
jsBinaryType = KotlinJsBinaryType.LIBRARY,
@@ -102,17 +102,6 @@ abstract class KotlinJsIrSubTarget(
}
}
private fun addLinkOptions(compilation: KotlinJsIrCompilation) {
val additionalCompilerOption = additionalCompilerOption ?: return
compilation.binaries
.withType(JsIrBinary::class.java)
.all {
it.linkTask.configure { linkTask ->
linkTask.kotlinOptions.freeCompilerArgs += additionalCompilerOption
}
}
}
private fun configureTestsRun(testRun: KotlinJsPlatformTestRun, compilation: KotlinJsIrCompilation) {
fun KotlinJsPlatformTestRun.subtargetTestTaskName(): String = disambiguateCamelCased(
lowerCamelCaseName(
@@ -121,8 +110,6 @@ abstract class KotlinJsIrSubTarget(
)
)
addLinkOptions(compilation)
val testJs = project.registerTask<KotlinJsTest>(
testRun.subtargetTestTaskName(),
listOf(compilation)
@@ -177,7 +164,6 @@ abstract class KotlinJsIrSubTarget(
protected abstract fun configureDefaultTestFramework(test: KotlinJsTest)
protected abstract fun configureTestDependencies(test: KotlinJsTest)
protected abstract val additionalCompilerOption: String?
private fun configureMain() {
target.compilations.all { compilation ->
@@ -43,7 +43,4 @@ open class KotlinNodeJsIr @Inject constructor(target: KotlinJsIrTarget) :
test.testFramework = KotlinWasmNode(test)
}
}
override val additionalCompilerOption: String?
get() = "-Xwasm-launcher=nodejs".takeIf { target.platformType == KotlinPlatformType.wasm }
}
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.gradle.targets.js.npm
import org.gradle.api.Project
import org.gradle.process.ExecSpec
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.disambiguateName
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsTargetDsl
@@ -28,6 +29,8 @@ val KotlinJsCompilation.npmProject: NpmProject
open class NpmProject(@Transient val compilation: KotlinJsCompilation) : Serializable {
val compilationName = compilation.disambiguatedName
private val extension = if (compilation.platformType == KotlinPlatformType.wasm) ".mjs" else ".js"
val name: String by lazy {
buildNpmProjectName()
}
@@ -65,7 +68,7 @@ open class NpmProject(@Transient val compilation: KotlinJsCompilation) : Seriali
get() = dir.resolve(DIST_FOLDER)
val main: String
get() = "$DIST_FOLDER/$name.js"
get() = "$DIST_FOLDER/$name$extension"
val externalsDirRoot by lazy {
project.buildDir.resolve("externals").resolve(name)
@@ -14,14 +14,19 @@ import org.jetbrains.kotlin.gradle.targets.js.RequiredKotlinJsDependency
import org.jetbrains.kotlin.gradle.targets.js.d8.D8RootPlugin
import org.jetbrains.kotlin.gradle.targets.js.internal.parseNodeJsStackTraceAsJvm
import org.jetbrains.kotlin.gradle.targets.js.isTeamCity
import org.jetbrains.kotlin.gradle.targets.js.writeWasmUnitTestRunner
import org.jetbrains.kotlin.gradle.utils.getValue
internal class KotlinWasmD8(private val kotlinJsTest: KotlinJsTest) : KotlinJsTestFramework {
override val settingsState: String = "KotlinWasmD8"
@Transient
override val compilation: KotlinJsCompilation = kotlinJsTest.compilation
@Transient
private val project: Project = compilation.target.project
private val d8 = D8RootPlugin.apply(project.rootProject)
private val d8Executable by project.provider { d8.requireConfigured().executablePath }
private val isTeamCity by lazy { project.isTeamCity }
init {
kotlinJsTest.outputs.upToDateWhen { false }
@@ -33,10 +38,10 @@ internal class KotlinWasmD8(private val kotlinJsTest: KotlinJsTest) : KotlinJsTe
nodeJsArgs: MutableList<String>,
debug: Boolean
): TCServiceMessagesTestExecutionSpec {
val compiledFile = task.inputFileProperty.get().asFile
val testRunnerFile = writeWasmUnitTestRunner(task.inputFileProperty.get().asFile)
forkOptions.executable = d8Executable.absolutePath
forkOptions.workingDir = compiledFile.parentFile
forkOptions.workingDir = testRunnerFile.parentFile
val clientSettings = TCServiceMessagesClientSettings(
task.name,
@@ -44,7 +49,7 @@ internal class KotlinWasmD8(private val kotlinJsTest: KotlinJsTest) : KotlinJsTe
prependSuiteName = true,
stackTraceParser = ::parseNodeJsStackTraceAsJvm,
ignoreOutOfRootNodes = true,
escapeTCMessagesInLog = project.isTeamCity
escapeTCMessagesInLog = isTeamCity
)
val cliArgs = KotlinTestRunnerCliArgs(
@@ -53,26 +58,20 @@ internal class KotlinWasmD8(private val kotlinJsTest: KotlinJsTest) : KotlinJsTe
)
val args = mutableListOf(
"--module",
compiledFile.absolutePath,
"--experimental-wasm-typed-funcref",
"--experimental-wasm-gc",
"--experimental-wasm-eh",
testRunnerFile.absolutePath,
)
args.add("--")
args.addAll(cliArgs.toList())
val dryRunArgs = mutableListOf<String>()
dryRunArgs.addAll(args)
dryRunArgs.add("--dryRun")
return TCServiceMessagesTestExecutionSpec(
forkOptions = forkOptions,
args = args,
checkExitCode = false,
clientSettings = clientSettings,
dryRunArgs = dryRunArgs
dryRunArgs = args + "--dryRun"
)
}
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.gradle.targets.js.testing
import org.gradle.api.Project
import org.gradle.process.ProcessForkOptions
import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesClientSettings
import org.jetbrains.kotlin.gradle.internal.testing.TCServiceMessagesTestExecutionSpec
@@ -13,11 +12,13 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJsCompilation
import org.jetbrains.kotlin.gradle.targets.js.RequiredKotlinJsDependency
import org.jetbrains.kotlin.gradle.targets.js.internal.parseNodeJsStackTraceAsJvm
import org.jetbrains.kotlin.gradle.targets.js.isTeamCity
import org.jetbrains.kotlin.gradle.targets.js.writeWasmUnitTestRunner
internal class KotlinWasmNode(private val kotlinJsTest: KotlinJsTest) : KotlinJsTestFramework {
override val settingsState: String = "KotlinWasmNode"
@Transient
override val compilation: KotlinJsCompilation = kotlinJsTest.compilation
private val project: Project = compilation.target.project
private val isTeamCity by lazy { compilation.target.project.isTeamCity }
init {
kotlinJsTest.outputs.upToDateWhen { false }
@@ -29,7 +30,7 @@ internal class KotlinWasmNode(private val kotlinJsTest: KotlinJsTest) : KotlinJs
nodeJsArgs: MutableList<String>,
debug: Boolean
): TCServiceMessagesTestExecutionSpec {
val compiledFile = task.inputFileProperty.get().asFile
val testRunnerFile = writeWasmUnitTestRunner(task.inputFileProperty.get().asFile)
val clientSettings = TCServiceMessagesClientSettings(
task.name,
@@ -37,7 +38,7 @@ internal class KotlinWasmNode(private val kotlinJsTest: KotlinJsTest) : KotlinJs
prependSuiteName = true,
stackTraceParser = ::parseNodeJsStackTraceAsJvm,
ignoreOutOfRootNodes = true,
escapeTCMessagesInLog = project.isTeamCity
escapeTCMessagesInLog = isTeamCity
)
val cliArgs = KotlinTestRunnerCliArgs(
@@ -47,22 +48,17 @@ internal class KotlinWasmNode(private val kotlinJsTest: KotlinJsTest) : KotlinJs
val args = mutableListOf<String>()
with(args) {
add("--experimental-wasm-typed-funcref")
add("--experimental-wasm-gc")
add("--experimental-wasm-eh")
add(compiledFile.absolutePath)
add(testRunnerFile.absolutePath)
addAll(cliArgs.toList())
}
val dryRunArgs = mutableListOf<String>()
dryRunArgs.addAll(args)
dryRunArgs.add("--dryRun")
return TCServiceMessagesTestExecutionSpec(
forkOptions = forkOptions,
args = args,
checkExitCode = false,
clientSettings = clientSettings,
dryRunArgs = dryRunArgs
dryRunArgs = args + "--dryRun"
)
}
@@ -61,6 +61,7 @@ class KotlinKarma(
private var configDirectory: File by property {
defaultConfigDirectory
}
private val isTeamCity by lazy { project.isTeamCity }
override val requiredNpmDependencies: Set<RequiredKotlinJsDependency>
get() = requiredDependencies + webpackConfig.getRequiredDependencies(versions)
@@ -380,7 +381,7 @@ class KotlinKarma(
prependSuiteName = true,
stackTraceParser = ::parseNodeJsStackTraceAsJvm,
ignoreOutOfRootNodes = true,
escapeTCMessagesInLog = project.isTeamCity
escapeTCMessagesInLog = isTeamCity
)
config.basePath = npmProject.nodeModulesDir.absolutePath
@@ -28,6 +28,7 @@ class KotlinMocha(@Transient override val compilation: KotlinJsCompilation, priv
private val project: Project = compilation.target.project
private val npmProject = compilation.npmProject
private val versions = NodeJsRootPlugin.apply(project.rootProject).versions
private val isTeamCity by lazy { project.isTeamCity }
override val settingsState: String
get() = "mocha"
@@ -59,7 +60,7 @@ class KotlinMocha(@Transient override val compilation: KotlinJsCompilation, priv
prependSuiteName = true,
stackTraceParser = ::parseNodeJsStackTraceAsJvm,
ignoreOutOfRootNodes = true,
escapeTCMessagesInLog = project.isTeamCity
escapeTCMessagesInLog = isTeamCity
)
val cliArgs = KotlinTestRunnerCliArgs(
@@ -68,3 +68,14 @@ val Project.isTeamCity: Boolean
} else {
project.hasProperty(TCServiceMessagesTestExecutor.TC_PROJECT_PROPERTY)
}
internal fun writeWasmUnitTestRunner(compiledFile: File): File {
val testRunnerFile = compiledFile.parentFile.resolve("runUnitTests.mjs")
testRunnerFile.writeText(
"""
import exports from '${compiledFile.absolutePath}';
exports.startUnitTests?.();
""".trimIndent()
)
return testRunnerFile
}
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.gradle.tasks.configuration
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinCompilationData
import org.jetbrains.kotlin.gradle.targets.js.ir.isProduceUnzippedKlib
import org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile
@@ -27,8 +28,9 @@ internal open class BaseKotlin2JsCompileConfig<TASK : Kotlin2JsCompile>(
task.incrementalJsKlib = propertiesProvider.incrementalJsKlib ?: true
task.outputFileProperty.value(task.project.provider {
val extensionName = if (compilation.platformType == KotlinPlatformType.wasm) ".mjs" else ".js"
task.kotlinOptions.outputFile?.let(::File)
?: task.destinationDirectory.locationOnly.get().asFile.resolve("${compilation.ownModuleName}.js")
?: task.destinationDirectory.locationOnly.get().asFile.resolve("${compilation.ownModuleName}$extensionName")
}).disallowChanges()
task.optionalOutputFile.fileProvider(task.outputFileProperty.flatMap { outputFile ->