diff --git a/build.gradle.kts b/build.gradle.kts index b8f998984..783d12d56 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -379,32 +379,21 @@ subprojects { for (target in mobileTargets(project)) { val native = createPairSourceSet(target.name) - target.isIos - when (target.name) { - "iosX64" -> native.dependsOn(ios) - "iosArm32" -> native.dependsOn(ios) - "iosArm64" -> native.dependsOn(ios) - "iosSimulatorArm64" -> native.dependsOn(ios) - - "watchosX86" -> native.dependsOn(watchos) - "watchosX64" -> native.dependsOn(watchos) - "watchosArm32" -> native.dependsOn(watchos) - "watchosArm64" -> native.dependsOn(watchos) - "watchosSimulatorArm64" -> native.dependsOn(watchos) - - "tvosX64" -> native.dependsOn(tvos) - "tvosArm64" -> native.dependsOn(tvos) - "tvosSimulatorArm64" -> native.dependsOn(tvos) + when { + target.isIos -> native.dependsOn(ios) + target.isWatchos -> native.dependsOn(watchos) + target.isTvos -> native.dependsOn(tvos) } } - for (baseName in listOf("nativeInteropMain", "posixInteropMain")) { + for (baseName in listOf("nativeInteropMain", "posixInteropMain", "darwinInteropMain")) { val nativeInteropMainFolder = file("src/$baseName/kotlin") if (nativeInteropMainFolder.isDirectory) { val currentNativeTarget = currentPlatformNativeTarget(project) // @TODO: Copy instead of use the same source folder for (target in allNativeTargets(project)) { - if (baseName.contains("Posix") && !target.isPosix) continue + if (baseName.contains("posix", ignoreCase = true) && !target.isPosix) continue + if (baseName.contains("darwin", ignoreCase = true) && !target.isApple) continue val sourceSet = this@sourceSets.maybeCreate("${target.name}Main") val folder = when { @@ -412,7 +401,7 @@ subprojects { else -> { file("build/${baseName}Copy${target.name}").also { outFolder -> outFolder.mkdirs() - copy { + sync { from(nativeInteropMainFolder) into(outFolder) } diff --git a/buildSrc/src/main/kotlin/com/soywiz/korlibs/modules/Targets.kt b/buildSrc/src/main/kotlin/com/soywiz/korlibs/modules/Targets.kt index 34df276e2..dc79c7250 100644 --- a/buildSrc/src/main/kotlin/com/soywiz/korlibs/modules/Targets.kt +++ b/buildSrc/src/main/kotlin/com/soywiz/korlibs/modules/Targets.kt @@ -12,6 +12,13 @@ val Project.doEnableKotlinMobileTvos: Boolean get() = rootProject.findProperty(" val Project.doEnableKotlinMobileWatchos: Boolean get() = rootProject.findProperty("enableKotlinMobileWatchos") == "true" val Project.doEnableKotlinRaspberryPi: Boolean get() = rootProject.findProperty("enableKotlinRaspberryPi") == "true" +val KotlinTarget.isX64: Boolean get() = this.name.endsWith("X64") +val KotlinTarget.isX86: Boolean get() = this.name.endsWith("X86") +val KotlinTarget.isArm32: Boolean get() = this.name.endsWith("Arm32") +val KotlinTarget.isArm64: Boolean get() = this.name.endsWith("Arm64") || !this.name.endsWith("SimulatorArm64") +val KotlinTarget.isArm32Hfp: Boolean get() = this.name.endsWith("Arm32Hfp") +val KotlinTarget.isSimulatorArm64: Boolean get() = this.name.endsWith("SimulatorArm64") + val KotlinTarget.isLinuxX64: Boolean get() = this.name == "linuxX64" val KotlinTarget.isLinuxArm64: Boolean get() = this.name == "linuxArm64" val KotlinTarget.isLinuxArm32Hfp: Boolean get() = this.name == "linuxArm32Hfp" && project.doEnableKotlinRaspberryPi @@ -34,6 +41,7 @@ val KotlinTarget.isTvosArm64: Boolean get() = this.name == "tvosArm64" val KotlinTarget.isTvos: Boolean get() = isTvosX64 || isTvosArm64 val KotlinTarget.isDesktop: Boolean get() = isWin || isLinux || isMacos val KotlinTarget.isPosix: Boolean get() = this is KotlinNativeTarget && !this.isWin +val KotlinTarget.isApple: Boolean get() = isMacos || isIos || isWatchos || isTvos val isWindows: Boolean get() = org.apache.tools.ant.taskdefs.condition.Os.isFamily(org.apache.tools.ant.taskdefs.condition.Os.FAMILY_WINDOWS) val isMacos: Boolean get() = org.apache.tools.ant.taskdefs.condition.Os.isFamily(org.apache.tools.ant.taskdefs.condition.Os.FAMILY_MAC) diff --git a/gradle.properties b/gradle.properties index e5db29eaa..0c5d37dcc 100644 --- a/gradle.properties +++ b/gradle.properties @@ -75,13 +75,15 @@ project.license.name=MIT project.license.url=https://raw.githubusercontent.com/korlibs/korge-next/master/korge/LICENSE.txt kotlin.native.disableCompilerDaemon=true +#kotlin.compiler.execution.strategy=in-process + #kotlin.mpp.enableCompatibilityMetadataVariant=true kotlin.mpp.enableGranularSourceSetsMetadata=true -kotlin.native.enableDependencyPropagation=false -kotlin.native.ignoreIncorrectDependencies=true #kotlin.mpp.enableCInteropCommonization=true -#kotlin.compiler.execution.strategy=in-process kotlin.mpp.stability.nowarn=true + +kotlin.native.enableDependencyPropagation=false +kotlin.native.ignoreIncorrectDependencies=true kotlin.native.ignoreDisabledTargets=true #org.gradle.caching=true diff --git a/klock/src/darwinMain/kotlin/com/soywiz/klock/internal/KlockInternal.kt b/klock/src/darwinMain/kotlin/com/soywiz/klock/internal/KlockInternal.kt new file mode 100644 index 000000000..9f7b5732f --- /dev/null +++ b/klock/src/darwinMain/kotlin/com/soywiz/klock/internal/KlockInternal.kt @@ -0,0 +1,39 @@ +package com.soywiz.klock.internal + +import com.soywiz.klock.* +import com.soywiz.klock.hr.* +import kotlinx.cinterop.* +import platform.CoreFoundation.* +import platform.posix.* + +internal actual object KlockInternal { + actual val currentTime: Double get() = memScoped { + val timeVal = alloc() + gettimeofday(timeVal.ptr, null) + val sec = timeVal.tv_sec + val usec = timeVal.tv_usec + ((sec * 1_000L) + (usec / 1_000L)).toDouble() + } + + actual val hrNow: HRTimeSpan get() = memScoped { + val timeVal = alloc() + gettimeofday(timeVal.ptr, null) + val sec = timeVal.tv_sec + val usec = timeVal.tv_usec + HRTimeSpan.fromSeconds(sec.toInt()) + HRTimeSpan.fromMicroseconds(usec.toInt()) + } + + actual fun sleep(time: HRTimeSpan) { + val micros = time.microsecondsDouble.toLong() + val s = micros / 1_000_000 + val u = micros % 1_000_000 + if (s > 0) platform.posix.sleep(s.convert()) + if (u > 0) platform.posix.usleep(u.convert()) + } + + actual fun localTimezoneOffsetMinutes(time: DateTime): TimeSpan = autoreleasepool { + val tz: CFTimeZoneRef? = CFTimeZoneCopySystem() + val minsFromGMT: CFTimeInterval = CFTimeZoneGetSecondsFromGMT(tz, CFAbsoluteTimeGetCurrent()) / 60.0 + minsFromGMT.minutes + } +} diff --git a/klock/src/posixMain/kotlin/com/soywiz/klock/internal/KlockInternal.kt b/klock/src/linuxMain/kotlin/com/soywiz/klock/internal/KlockInternal.kt similarity index 100% rename from klock/src/posixMain/kotlin/com/soywiz/klock/internal/KlockInternal.kt rename to klock/src/linuxMain/kotlin/com/soywiz/klock/internal/KlockInternal.kt diff --git a/korim/src/darwinMain/kotlin/com/soywiz/korim/format/cg/CgRenderer.kt b/korim/src/darwinMain/kotlin/com/soywiz/korim/format/cg/CgRenderer.kt index b5e9e935f..be491fad1 100644 --- a/korim/src/darwinMain/kotlin/com/soywiz/korim/format/cg/CgRenderer.kt +++ b/korim/src/darwinMain/kotlin/com/soywiz/korim/format/cg/CgRenderer.kt @@ -178,7 +178,7 @@ class CoreGraphicsRenderer(val bmp: Bitmap32, val antialiasing: Boolean) : com.s } is GradientPaint -> { val nelements = style.colors.size - val colors = CFArrayCreateMutable(null, nelements.toLong(), null) + val colors = CFArrayCreateMutable(null, nelements.convert(), null) val locations = allocArray(nelements) for (n in 0 until nelements) { val color = RGBA(style.colors[n]) diff --git a/korio/src/darwinMain/kotlin/com/soywiz/korio/process/ProcessApple.kt b/korio/src/darwinMain/kotlin/com/soywiz/korio/process/ProcessApple.kt index e86d33f1d..28b494422 100644 --- a/korio/src/darwinMain/kotlin/com/soywiz/korio/process/ProcessApple.kt +++ b/korio/src/darwinMain/kotlin/com/soywiz/korio/process/ProcessApple.kt @@ -1,6 +1,8 @@ package com.soywiz.korio.process import com.soywiz.korio.file.VfsProcessHandler +import kotlinx.cinterop.* +import platform.posix.* actual suspend fun posixExec( path: String, cmdAndArgs: List, env: Map, handler: VfsProcessHandler diff --git a/korio/src/nativeMain/kotlin/com/soywiz/korio/process/ProcessNative.kt b/korio/src/nativeMain/kotlin/com/soywiz/korio/process/ProcessNative.kt index 6cd4eac90..c61a4f6e8 100644 --- a/korio/src/nativeMain/kotlin/com/soywiz/korio/process/ProcessNative.kt +++ b/korio/src/nativeMain/kotlin/com/soywiz/korio/process/ProcessNative.kt @@ -1,6 +1,8 @@ package com.soywiz.korio.process import com.soywiz.korio.file.VfsProcessHandler +import kotlinx.cinterop.* +import platform.posix.* expect suspend fun posixExec( path: String, cmdAndArgs: List, env: Map, handler: VfsProcessHandler diff --git a/korio/src/posixInteropMain/kotlin/com/soywiz/korio/posix/PosixExt.kt b/korio/src/posixInteropMain/kotlin/com/soywiz/korio/posix/PosixExt.kt new file mode 100644 index 000000000..9244d675f --- /dev/null +++ b/korio/src/posixInteropMain/kotlin/com/soywiz/korio/posix/PosixExt.kt @@ -0,0 +1,24 @@ +package com.soywiz.korio.posix + +import platform.posix.* +import kotlinx.cinterop.* + +internal actual fun posixFread(__ptr: CValuesRef<*>?, __size: Long, __nitems: Long, __stream: CValuesRef?): ULong { + return fread(__ptr, __size.convert(), __nitems.convert(), __stream).convert() +} + +internal actual fun posixFwrite(__ptr: CValuesRef<*>?, __size: Long, __nitems: Long, __stream: CValuesRef?): ULong { + return fwrite(__ptr, __size.convert(), __nitems.convert(), __stream).convert() +} + +internal actual fun posixFseek(file: CValuesRef?, offset: Long, whence: Int): Int { + return fseek(file, offset.convert(), whence.convert()) +} + +internal actual fun posixFtell(file: CValuesRef?): ULong { + return ftell(file).convert() +} + +internal actual fun ioctlFionRead(sockfd: Int, ptr: CValuesRef) { + ioctl(sockfd, FIONREAD, ptr) +} diff --git a/korio/src/nativeMain/kotlin/com/soywiz/korio/file/std/LocalVfsNative.kt b/korio/src/posixMain/kotlin/com/soywiz/korio/file/std/LocalVfsNative.kt similarity index 92% rename from korio/src/nativeMain/kotlin/com/soywiz/korio/file/std/LocalVfsNative.kt rename to korio/src/posixMain/kotlin/com/soywiz/korio/file/std/LocalVfsNative.kt index 7a608b908..abc848c57 100644 --- a/korio/src/nativeMain/kotlin/com/soywiz/korio/file/std/LocalVfsNative.kt +++ b/korio/src/posixMain/kotlin/com/soywiz/korio/file/std/LocalVfsNative.kt @@ -23,6 +23,8 @@ import kotlinx.cinterop.* import platform.posix.* import kotlin.native.concurrent.* import com.soywiz.korio.lang.Environment +import com.soywiz.korio.posix.* +import com.soywiz.korio.posix.posixFread import com.soywiz.korio.process.posixExec @ThreadLocal @@ -81,9 +83,9 @@ open class LocalVfsNativeBase(val async: Boolean = true) : LocalVfsV2() { return executeInIOWorker(Info(rpath, range)) { (rpath, range) -> val fd = posixFopen(rpath, "rb") if (fd != null) { - fseek(fd, 0L.convert(), SEEK_END) + posixFseek(fd, 0L.convert(), SEEK_END) //val length = ftell(fd).toLong() // @TODO: Kotlin native bug? - val length: Long = ftell(fd).convert() + val length: Long = posixFtell(fd).convert() val start = min(range.start, length) val end = min(range.endInclusive, length - 1) + 1 @@ -98,8 +100,8 @@ open class LocalVfsNativeBase(val async: Boolean = true) : LocalVfsV2() { val byteArray = ByteArray(totalRead) val finalRead = if (byteArray.isNotEmpty()) { byteArray.usePinned { pin -> - fseek(fd, start.convert(), SEEK_SET) - fread(pin.addressOf(0), 1.convert(), totalRead.convert(), fd).toInt() + posixFseek(fd, start.convert(), SEEK_SET) + posixFread(pin.addressOf(0), 1.convert(), totalRead.convert(), fd).toInt() } } else { 0 @@ -122,9 +124,9 @@ open class LocalVfsNativeBase(val async: Boolean = true) : LocalVfsV2() { val (initialFd, initialFileLength) = executeInIOWorker(FileOpenInfo(rpath, mode.cmode)) { it -> val fd = posixFopen(it.name, it.mode) val len = if (fd != null) { - fseek(fd, 0L.convert(), SEEK_END) - val end = ftell(fd) - fseek(fd, 0L.convert(), SEEK_SET) + posixFseek(fd, 0L.convert(), SEEK_END) + val end = posixFtell(fd) + posixFseek(fd, 0L.convert(), SEEK_SET) end.toLong() } else { 0L @@ -155,13 +157,13 @@ open class LocalVfsNativeBase(val async: Boolean = true) : LocalVfsV2() { val time = measureTime { transferredCount = buffer.usePinned { pin -> executeInIOWorker(Info(fd, position, pin.addressOf(offset), len, write)) { (fd, position, buffer, len) -> - fseek(fd, position.convert(), SEEK_SET) + posixFseek(fd, position.convert(), SEEK_SET) if (write) { //platform.posix.fwrite(buffer, 1.convert(), len.convert(), fd).toLong() - fwrite(buffer, len.convert(), 1.convert(), fd).toLong() // Write it at once (len, 1) + posixFwrite(buffer, len.convert(), 1.convert(), fd).toLong() // Write it at once (len, 1) len.toLong() } else { - fread(buffer, 1.convert(), len.convert(), fd).toLong() // Allow to read less values (1, len) + posixFread(buffer, 1.convert(), len.convert(), fd).toLong() // Allow to read less values (1, len) } } } diff --git a/korio/src/posixMain/kotlin/com/soywiz/korio/net/NativeSocket.kt b/korio/src/posixMain/kotlin/com/soywiz/korio/net/NativeSocket.kt index a9a81018e..460dd1f22 100644 --- a/korio/src/posixMain/kotlin/com/soywiz/korio/net/NativeSocket.kt +++ b/korio/src/posixMain/kotlin/com/soywiz/korio/net/NativeSocket.kt @@ -1,4 +1,5 @@ package com.soywiz.korio.net +import com.soywiz.korio.posix.* import kotlinx.cinterop.* import kotlinx.coroutines.* import platform.posix.* @@ -121,7 +122,7 @@ class NativeSocket private constructor(internal val sockfd: Int, private var end val availableBytes: Int get() { val bytes_available = intArrayOf(0, 0) - ioctl(sockfd, FIONREAD, bytes_available.refTo(0)) + ioctlFionRead(sockfd, bytes_available.refTo(0)) return bytes_available[0] } diff --git a/korio/src/posixMain/kotlin/com/soywiz/korio/posix/PosixExtExpect.kt b/korio/src/posixMain/kotlin/com/soywiz/korio/posix/PosixExtExpect.kt new file mode 100644 index 000000000..9d4cfdbd1 --- /dev/null +++ b/korio/src/posixMain/kotlin/com/soywiz/korio/posix/PosixExtExpect.kt @@ -0,0 +1,10 @@ +package com.soywiz.korio.posix + +import kotlinx.cinterop.* +import platform.posix.* + +internal expect fun posixFread(__ptr: CValuesRef<*>?, __size: Long, __nitems: Long, __stream: CValuesRef?): ULong +internal expect fun posixFwrite(__ptr: CValuesRef<*>?, __size: Long, __nitems: Long, __stream: CValuesRef?): ULong +internal expect fun posixFseek(file: CValuesRef?, offset: Long, whence: Int): Int +internal expect fun posixFtell(file: CValuesRef?): ULong +internal expect fun ioctlFionRead(sockfd: Int, ptr: CValuesRef)