Unverified Commit ea433be9 authored by Alexey Tsvetkov's avatar Alexey Tsvetkov Committed by GitHub

Skip compiling native bridges for incompatible OS (#390)

* Skip compiling native bridges for incompatible OS

* Move all JS configuration under supportWasm flag

* Suppress OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE in tests

Otherwise, test compilation fails,
when wasm & native are disabled,
i.e. only jvm target is active,
which leads to https://youtrack.jetbrains.com/issue/KT-44014
parent b5e2a775
...@@ -38,9 +38,10 @@ val windowsSdkPaths: WindowsSdkPaths by lazy { ...@@ -38,9 +38,10 @@ val windowsSdkPaths: WindowsSdkPaths by lazy {
findWindowsSdkPathsForCurrentOS(gradle) findWindowsSdkPathsForCurrentOS(gradle)
} }
val skiaWasmDir = registerOrGetSkiaDirProvider(OS.Wasm, Arch.Wasm) if (supportWasm) {
val skiaWasmDir = registerOrGetSkiaDirProvider(OS.Wasm, Arch.Wasm)
val compileWasm = tasks.register<CompileSkikoCppTask>("compileWasm") { val compileWasm by tasks.registering(CompileSkikoCppTask::class) {
val osArch = OS.Wasm to Arch.Wasm val osArch = OS.Wasm to Arch.Wasm
dependsOn(skiaWasmDir) dependsOn(skiaWasmDir)
...@@ -64,6 +65,67 @@ val compileWasm = tasks.register<CompileSkikoCppTask>("compileWasm") { ...@@ -64,6 +65,67 @@ val compileWasm = tasks.register<CompileSkikoCppTask>("compileWasm") {
"-fno-rtti", "-fno-rtti",
"-fno-exceptions" "-fno-exceptions"
)) ))
}
val linkWasm by tasks.registering(LinkSkikoWasmTask::class) {
val osArch = OS.Wasm to Arch.Wasm
dependsOn(compileWasm)
dependsOn(skiaWasmDir)
val unpackedSkia = skiaWasmDir.get()
linker.set(linkerForTarget(OS.Wasm, Arch.Wasm))
buildTargetOS.set(osArch.first)
buildTargetArch.set(osArch.second)
buildVariant.set(buildType)
libFiles = project.fileTree(unpackedSkia) { include("**/*.a") }
objectFiles = project.fileTree(compileWasm.map { it.outDir.get() }) {
include("**/*.o")
}
libOutputFileName.set("skiko.wasm")
jsOutputFileName.set("skiko.js")
skikoJsPrefix.set(project.layout.projectDirectory.file("src/jsMain/resources/setup.js"))
flags.set(listOf(
"-l", "GL",
"-s", "USE_WEBGL2=1",
"-s", "OFFSCREEN_FRAMEBUFFER=1",
"-s", "ALLOW_MEMORY_GROWTH=1", // TODO: Is there a better way? Should we use `-s INITIAL_MEMORY=X`?
"--bind",
))
doLast {
// skiko.js file is directly referenced in karma.config.d/wasm.js
// so symbols must be replaced right after linking
val jsFiles = outDir.asFile.get().walk()
.filter { it.isFile && it.name.endsWith(".js") }
for (jsFile in jsFiles) {
val originalContent = jsFile.readText()
val newContent = originalContent.replace("_org_jetbrains", "org_jetbrains")
jsFile.writeText(newContent)
}
}
}
val skikoWasmJar by project.tasks.registering(Jar::class) {
dependsOn(linkWasm)
// We produce jar that contains .js of wrapper/bindings and .wasm with Skia + bindings.
val wasmOutDir = linkWasm.map { it.outDir }
from(wasmOutDir) {
include("*.wasm")
include("*.js")
}
archiveBaseName.set("skiko-wasm")
doLast {
println("Wasm and JS at: ${archiveFile.get().asFile.absolutePath}")
}
}
} }
fun compileNativeBridgesTask(os: OS, arch: Arch): TaskProvider<CompileSkikoCppTask> { fun compileNativeBridgesTask(os: OS, arch: Arch): TaskProvider<CompileSkikoCppTask> {
...@@ -142,50 +204,6 @@ fun compileNativeBridgesTask(os: OS, arch: Arch): TaskProvider<CompileSkikoCppTa ...@@ -142,50 +204,6 @@ fun compileNativeBridgesTask(os: OS, arch: Arch): TaskProvider<CompileSkikoCppTa
} }
} }
val linkWasm = tasks.register<LinkSkikoWasmTask>("linkWasm") {
val osArch = OS.Wasm to Arch.Wasm
dependsOn(compileWasm)
dependsOn(skiaWasmDir)
val unpackedSkia = skiaWasmDir.get()
linker.set(linkerForTarget(OS.Wasm, Arch.Wasm))
buildTargetOS.set(osArch.first)
buildTargetArch.set(osArch.second)
buildVariant.set(buildType)
libFiles = project.fileTree(unpackedSkia) { include("**/*.a") }
objectFiles = project.fileTree(compileWasm.map { it.outDir.get() }) {
include("**/*.o")
}
libOutputFileName.set("skiko.wasm")
jsOutputFileName.set("skiko.js")
skikoJsPrefix.set(project.layout.projectDirectory.file("src/jsMain/resources/setup.js"))
flags.set(listOf(
"-l", "GL",
"-s", "USE_WEBGL2=1",
"-s", "OFFSCREEN_FRAMEBUFFER=1",
"-s", "ALLOW_MEMORY_GROWTH=1", // TODO: Is there a better way? Should we use `-s INITIAL_MEMORY=X`?
"--bind",
))
doLast {
// skiko.js file is directly referenced in karma.config.d/wasm.js
// so symbols must be replaced right after linking
val jsFiles = outDir.asFile.get().walk()
.filter { it.isFile && it.name.endsWith(".js") }
for (jsFile in jsFiles) {
val originalContent = jsFile.readText()
val newContent = originalContent.replace("_org_jetbrains", "org_jetbrains")
jsFile.writeText(newContent)
}
}
}
val skiaBinSubdir = "out/${buildType.id}-${targetOs.id}-${targetArch.id}" val skiaBinSubdir = "out/${buildType.id}-${targetOs.id}-${targetArch.id}"
internal val Project.isInIdea: Boolean internal val Project.isInIdea: Boolean
...@@ -206,10 +224,11 @@ kotlin { ...@@ -206,10 +224,11 @@ kotlin {
} }
} }
if (supportWasm) {
js(IR) { js(IR) {
browser() { browser() {
testTask { testTask {
dependsOn(linkWasm) dependsOn("linkWasm")
useKarma { useKarma {
useChromeHeadless() useChromeHeadless()
} }
...@@ -217,6 +236,7 @@ kotlin { ...@@ -217,6 +236,7 @@ kotlin {
} }
binaries.executable() binaries.executable()
} }
}
if (supportNative) { if (supportNative) {
configureNativeTarget(OS.MacOS, Arch.X64, macosX64()) configureNativeTarget(OS.MacOS, Arch.X64, macosX64())
...@@ -255,6 +275,7 @@ kotlin { ...@@ -255,6 +275,7 @@ kotlin {
} }
} }
if (supportWasm || supportNative) {
val nativeJsMain by creating { val nativeJsMain by creating {
dependsOn(commonMain) dependsOn(commonMain)
} }
...@@ -263,6 +284,7 @@ kotlin { ...@@ -263,6 +284,7 @@ kotlin {
dependsOn(commonTest) dependsOn(commonTest)
} }
if (supportWasm) {
val jsMain by getting { val jsMain by getting {
dependsOn(nativeJsMain) dependsOn(nativeJsMain)
} }
...@@ -274,6 +296,7 @@ kotlin { ...@@ -274,6 +296,7 @@ kotlin {
implementation(kotlin("test-js")) implementation(kotlin("test-js"))
} }
} }
}
if (supportNative) { if (supportNative) {
// See https://kotlinlang.org/docs/mpp-share-on-platforms.html#configure-the-hierarchical-structure-manually // See https://kotlinlang.org/docs/mpp-share-on-platforms.html#configure-the-hierarchical-structure-manually
...@@ -342,9 +365,12 @@ kotlin { ...@@ -342,9 +365,12 @@ kotlin {
} }
} }
} }
}
} }
fun configureNativeTarget(os: OS, arch: Arch, target: KotlinNativeTarget) { fun configureNativeTarget(os: OS, arch: Arch, target: KotlinNativeTarget) {
if (!os.isCompatibleWithHost) return
val targetString = "${os.id}-${arch.id}" val targetString = "${os.id}-${arch.id}"
val unzipper = registerOrGetSkiaDirProvider(os, arch) val unzipper = registerOrGetSkiaDirProvider(os, arch)
...@@ -899,22 +925,6 @@ val skikoJvmRuntimeJar by project.tasks.registering(Jar::class) { ...@@ -899,22 +925,6 @@ val skikoJvmRuntimeJar by project.tasks.registering(Jar::class) {
from(createChecksums.map { it.outputs.files }) from(createChecksums.map { it.outputs.files })
} }
val skikoWasmJar by project.tasks.registering(Jar::class) {
dependsOn(linkWasm)
// We produce jar that contains .js of wrapper/bindings and .wasm with Skia + bindings.
val wasmOutDir = linkWasm.map { it.outDir }
from(wasmOutDir) {
include("*.wasm")
include("*.js")
}
archiveBaseName.set("skiko-wasm")
doLast {
println("Wasm and JS at: ${archiveFile.get().asFile.absolutePath}")
}
}
val skikoRuntimeDirForTests by project.tasks.registering(Copy::class) { val skikoRuntimeDirForTests by project.tasks.registering(Copy::class) {
dependsOn(skikoJvmRuntimeJar) dependsOn(skikoJvmRuntimeJar)
from(zipTree(skikoJvmRuntimeJar.flatMap { it.archiveFile })) { from(zipTree(skikoJvmRuntimeJar.flatMap { it.archiveFile })) {
...@@ -1060,7 +1070,7 @@ publishing { ...@@ -1060,7 +1070,7 @@ publishing {
create<MavenPublication>("skikoWasmRuntime") { create<MavenPublication>("skikoWasmRuntime") {
pomNameForPublication[name] = "Skiko WASM Runtime" pomNameForPublication[name] = "Skiko WASM Runtime"
artifactId = SkikoArtifacts.jsWasmArtifactId artifactId = SkikoArtifacts.jsWasmArtifactId
artifact(skikoWasmJar.get()) artifact(tasks.named("skikoWasmJar").get())
artifact(emptySourcesJar) artifact(emptySourcesJar)
} }
} }
......
...@@ -17,6 +17,14 @@ enum class OS( ...@@ -17,6 +17,14 @@ enum class OS(
get() = this == Windows get() = this == Windows
} }
val OS.isCompatibleWithHost: Boolean
get() = when (this) {
OS.Linux -> hostOs == OS.Linux
OS.Windows -> hostOs == OS.Windows
OS.MacOS, OS.IOS -> hostOs == OS.MacOS
OS.Wasm -> true
}
fun compilerForTarget(os: OS, arch: Arch): String = fun compilerForTarget(os: OS, arch: Arch): String =
when (os) { when (os) {
OS.Linux -> when (arch) { OS.Linux -> when (arch) {
......
package org.jetbrains.skiko.tests package org.jetbrains.skiko.tests
import org.jetbrains.skia.ExternalSymbolName import org.jetbrains.skia.*
import org.jetbrains.skia.impl.* import org.jetbrains.skia.impl.*
internal class TestGlContext : Managed(TestGlContext_nCreate(), FinalizerHolder.PTR) { internal class TestGlContext : Managed(TestGlContext_nCreate(), FinalizerHolder.PTR) {
...@@ -78,39 +78,48 @@ class TestHelpers { ...@@ -78,39 +78,48 @@ class TestHelpers {
} }
} }
@Suppress("OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE") // See KT-44014
@ExternalSymbolName("org_jetbrains_skiko_tests_TestHelpers__1nFillByteArrayOf5") @ExternalSymbolName("org_jetbrains_skiko_tests_TestHelpers__1nFillByteArrayOf5")
private external fun _nFillByteArrayOf5(interopPointer: InteropPointer) private external fun _nFillByteArrayOf5(interopPointer: InteropPointer)
@Suppress("OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE") // See KT-44014
@ExternalSymbolName("org_jetbrains_skiko_tests_TestHelpers__1nFillFloatArrayOf5") @ExternalSymbolName("org_jetbrains_skiko_tests_TestHelpers__1nFillFloatArrayOf5")
private external fun _nFillFloatArrayOf5(interopPointer: InteropPointer) private external fun _nFillFloatArrayOf5(interopPointer: InteropPointer)
@Suppress("OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE") // See KT-44014
@ExternalSymbolName("org_jetbrains_skiko_tests_TestHelpers__1nFillShortArrayOf5") @ExternalSymbolName("org_jetbrains_skiko_tests_TestHelpers__1nFillShortArrayOf5")
private external fun _nFillShortArrayOf5(interopPointer: InteropPointer) private external fun _nFillShortArrayOf5(interopPointer: InteropPointer)
@Suppress("OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE") // See KT-44014
@ExternalSymbolName("org_jetbrains_skiko_tests_TestHelpers__1nFillIntArrayOf5") @ExternalSymbolName("org_jetbrains_skiko_tests_TestHelpers__1nFillIntArrayOf5")
private external fun _nFillIntArrayOf5(interopPointer: InteropPointer) private external fun _nFillIntArrayOf5(interopPointer: InteropPointer)
@Suppress("OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE") // See KT-44014
@ExternalSymbolName("org_jetbrains_skiko_tests_TestHelpers__1nFillDoubleArrayOf5") @ExternalSymbolName("org_jetbrains_skiko_tests_TestHelpers__1nFillDoubleArrayOf5")
private external fun _nFillDoubleArrayOf5(interopPointer: InteropPointer) private external fun _nFillDoubleArrayOf5(interopPointer: InteropPointer)
@Suppress("OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE") // See KT-44014
@ExternalSymbolName("org_jetbrains_skiko_tests_TestHelpers__1nWriteArraysOfInts") @ExternalSymbolName("org_jetbrains_skiko_tests_TestHelpers__1nWriteArraysOfInts")
private external fun _nWriteArraysOfInts(interopPointer: InteropPointer): NativePointer private external fun _nWriteArraysOfInts(interopPointer: InteropPointer): NativePointer
@Suppress("OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE") // See KT-44014
@ExternalSymbolName("org_jetbrains_skiko_tests_TestHelpers__nStringByIndex") @ExternalSymbolName("org_jetbrains_skiko_tests_TestHelpers__nStringByIndex")
private external fun _nStringByIndex(index: Int): NativePointer private external fun _nStringByIndex(index: Int): NativePointer
internal fun nativeStringByIndex(index: Int): NativePointer = _nStringByIndex(index) internal fun nativeStringByIndex(index: Int): NativePointer = _nStringByIndex(index)
@Suppress("OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE") // See KT-44014
@ExternalSymbolName("org_jetbrains_skiko_tests_TestHelpers__1nCreateTestGlContext") @ExternalSymbolName("org_jetbrains_skiko_tests_TestHelpers__1nCreateTestGlContext")
private external fun TestGlContext_nCreate(): NativePointer private external fun TestGlContext_nCreate(): NativePointer
@Suppress("OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE") // See KT-44014
@ExternalSymbolName("org_jetbrains_skiko_tests_TestHelpers__1nGlContextGetFinalizer") @ExternalSymbolName("org_jetbrains_skiko_tests_TestHelpers__1nGlContextGetFinalizer")
private external fun TestGlContext_nGetFinalizer(): NativePointer private external fun TestGlContext_nGetFinalizer(): NativePointer
@Suppress("OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE") // See KT-44014
@ExternalSymbolName("org_jetbrains_skiko_tests_TestHelpers__1nMakeGlContextCurrent") @ExternalSymbolName("org_jetbrains_skiko_tests_TestHelpers__1nMakeGlContextCurrent")
private external fun TestGlContext_nMakeCurrent(ptr: NativePointer) private external fun TestGlContext_nMakeCurrent(ptr: NativePointer)
@Suppress("OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE") // See KT-44014
@ExternalSymbolName("org_jetbrains_skiko_tests_TestHelpers__1nGlContextSwapBuffers") @ExternalSymbolName("org_jetbrains_skiko_tests_TestHelpers__1nGlContextSwapBuffers")
private external fun TestGlContext_nSwapBuffers(ptr: NativePointer) private external fun TestGlContext_nSwapBuffers(ptr: NativePointer)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment