Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
build:
strategy:
matrix:
os: [macOS-latest, windows-latest]
os: [ macOS-latest, windows-latest, ubuntu-18.04 ]
runs-on: ${{matrix.os}}
steps:
- name: Checkout the repo
Expand Down
9 changes: 8 additions & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
build:
strategy:
matrix:
os: [macOS-latest, windows-latest]
os: [ macOS-latest, windows-latest, ubuntu-18.04 ]
runs-on: ${{matrix.os}}
steps:
- name: Checkout the repo
Expand Down Expand Up @@ -58,6 +58,13 @@ jobs:
ORG_GRADLE_PROJECT_SONATYPE_NEXUS_USERNAME: ${{ secrets.SONATYPE_NEXUS_USERNAME }}
ORG_GRADLE_PROJECT_SONATYPE_NEXUS_PASSWORD: ${{ secrets.SONATYPE_NEXUS_PASSWORD }}
ORG_GRADLE_PROJECT_SIGNING_KEY: ${{ secrets.SIGNING_KEY }}
- name: Publish Linux Artifacts
if: matrix.os == 'ubuntu-latest'
run: ./gradlew publishLinux --no-daemon --stacktrace
env:
ORG_GRADLE_PROJECT_SONATYPE_NEXUS_USERNAME: ${{ secrets.SONATYPE_NEXUS_USERNAME }}
ORG_GRADLE_PROJECT_SONATYPE_NEXUS_PASSWORD: ${{ secrets.SONATYPE_NEXUS_PASSWORD }}
ORG_GRADLE_PROJECT_SIGNING_KEY: ${{ secrets.SIGNING_KEY }}

env:
GRADLE_OPTS: -Dorg.gradle.configureondemand=true -Dkotlin.incremental=false -Dorg.gradle.jvmargs="-Xmx3g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:MaxMetaspaceSize=512m"
4 changes: 4 additions & 0 deletions gradle/gradle-mvn-mpp-push.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,7 @@ publishing {
tasks.register('publishWindows') {
dependsOn 'publishMingwPublicationToMavenRepository'
}

tasks.register('publishLinux') {
dependsOn 'publishLinuxX64PublicationToMavenRepository'
}
86 changes: 53 additions & 33 deletions sqliter-driver/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import org.jetbrains.kotlin.konan.target.HostManager

plugins {
kotlin("multiplatform") version "1.5.0"
}
Expand All @@ -13,36 +15,42 @@ fun configInterop(target: org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTar
val sqlite3 by main.cinterops.creating {
includeDirs("$projectDir/src/include")
}
}

val onWindows = org.jetbrains.kotlin.konan.target.HostManager.hostIsMingw

kotlin {
val knTargets = listOf(
macosX64(),
iosX64(),
iosArm64(),
iosArm32(),
watchosArm32(),
watchosArm64(),
watchosX86(),
watchosX64(),
tvosArm64(),
tvosX64(),
mingwX64("mingw") {
compilations.forEach {
it.kotlinOptions.freeCompilerArgs += listOf("-linker-options", "-Lc:\\msys64\\mingw64\\lib")
}
target.compilations.forEach { kotlinNativeCompilation ->
kotlinNativeCompilation.kotlinOptions.freeCompilerArgs += when {
HostManager.hostIsLinux -> listOf(
"-linker-options",
"-lsqlite3 -L/usr/lib/x86_64-linux-gnu -L/usr/lib"
)
HostManager.hostIsMingw -> listOf("-linker-options", "-lsqlite3 -Lc:\\msys64\\mingw64\\lib")
else -> listOf("-linker-options", "-lsqlite3")
}
)

knTargets.forEach { configInterop(it) }
}
}

knTargets.forEach { target ->
val test by target.compilations.getting
test.kotlinOptions.freeCompilerArgs += listOf("-linker-options", "-lsqlite3")
kotlin {
val knTargets = when {
HostManager.hostIsMingw -> listOf(mingwX64("mingw"))
HostManager.hostIsLinux -> listOf(linuxX64())
else -> listOf(
macosX64(),
iosX64(),
iosArm64(),
iosArm32(),
watchosArm32(),
watchosArm64(),
watchosX86(),
watchosX64(),
tvosArm64(),
tvosX64()
)
}

knTargets
.forEach { target ->
configInterop(target)
}

sourceSets {
commonMain {
dependencies {
Expand All @@ -62,21 +70,33 @@ kotlin {
val appleMain = sourceSets.maybeCreate("appleMain").apply {
dependsOn(nativeCommonMain)
}
val linuxMain = sourceSets.maybeCreate("linuxX64Main").apply {
dependsOn(nativeCommonMain)
}


val mingwMain = sourceSets.maybeCreate("mingwMain").apply {
dependsOn(nativeCommonMain)
}
knTargets.forEach { target ->
if (target.name.startsWith("mingw")) {
target.compilations.getByName("main").source(mingwMain)
target.compilations.getByName("test").source(nativeCommonTest)
} else {
target.compilations.getByName("main").source(appleMain)
target.compilations.getByName("test").source(nativeCommonTest)
when {
target.name.startsWith("mingw") -> {
target.compilations.getByName("main").source(mingwMain)
target.compilations.getByName("test").source(nativeCommonTest)
}
target.name.startsWith("linux") -> {
target.compilations.getByName("main").source(linuxMain)
target.compilations.getByName("test").source(nativeCommonTest)
}
else -> {
target.compilations.getByName("main").source(appleMain)
target.compilations.getByName("test").source(nativeCommonTest)
}
}
}

}
}
}

apply(from = "../gradle/gradle-mvn-mpp-push.gradle")
apply(from = "../gradle/gradle-mvn-mpp-push.gradle")

Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package co.touchlab.sqliter

import co.touchlab.sqliter.internal.File
import co.touchlab.sqliter.internal.FileFilter
import kotlinx.cinterop.memScoped
import kotlinx.cinterop.refTo
import kotlinx.cinterop.toKString
import platform.posix.NULL
import platform.posix.PATH_MAX
import platform.posix.getcwd
import platform.posix.getenv

actual object DatabaseFileContext {
actual fun deleteDatabase(name: String, basePath: String?) {
deleteDatabaseFile(databaseFile(name, basePath))
}

actual fun databasePath(databaseName: String, datapathPath: String?): String {
return databaseFile(databaseName, datapathPath).path
}

internal fun databaseDirPath(): String {
return getHomeDirPath() ?: memScoped {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually here I'm not sure where the fallback path should lead to?
I just defined the home dir but of course this is suboptimal. But another arbitrary fallback dir is also IMO. But you did something similar on windows as well and one should configure the path anyways in most cases.
Maybe you have a preference where the fallback path should be? Or is home fine for you?

val buff = ByteArray(PATH_MAX)
if (getcwd(buff.refTo(0), buff.size.toULong()) != NULL) {
return buff.toKString()
}
throw IllegalStateException("Cannot get home dir or current dir")
}
}

internal fun getHomeDirPath(): String? = getenv("HOME")?.toKString()

internal fun databaseFile(databaseName: String, datapathPath: String?): File =
File(datapathPath ?: databaseDirPath(), databaseName)

internal fun deleteDatabaseFile(file: File): Boolean {
var deleted = false
deleted = deleted or file.delete()
deleted = deleted or File(file.getPath() + "-journal").delete()
deleted = deleted or File(file.getPath() + "-shm").delete()
deleted = deleted or File(file.getPath() + "-wal").delete()

//TODO: Implement file list
val dir = file.getParentFile()
if (dir != null) {
val prefix = file.getName() + "-mj"
val files = dir.listFiles(object : FileFilter {
override fun accept(candidate: File): Boolean {
return candidate.getName().startsWith(prefix)
}
})
if (files != null) {
for (masterJournal in files) {
deleted = deleted or masterJournal.delete()
}
}
}
return deleted
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package co.touchlab.sqliter.concurrency

import kotlinx.cinterop.Arena
import kotlinx.cinterop.alloc
import kotlinx.cinterop.ptr
import platform.posix.*
import kotlin.native.concurrent.freeze

/**
* A simple lock.
* Implementations of this class should be re-entrant.
*/
actual class Lock actual constructor() {
private val arena = Arena()
private val attr = arena.alloc<pthread_mutexattr_t>()
private val mutex = arena.alloc<pthread_mutex_t>()

init {
pthread_mutexattr_init(attr.ptr)
pthread_mutexattr_settype(attr.ptr, PTHREAD_MUTEX_RECURSIVE.toInt())
pthread_mutex_init(mutex.ptr, attr.ptr)
freeze()
}

actual fun lock() {
pthread_mutex_lock(mutex.ptr)
}

actual fun unlock() {
pthread_mutex_unlock(mutex.ptr)
}

actual fun tryLock(): Boolean = pthread_mutex_trylock(mutex.ptr) == 0

fun internalClose() {
pthread_mutex_destroy(mutex.ptr)
pthread_mutexattr_destroy(attr.ptr)
arena.clear()
}
}

actual inline fun Lock.close() {
internalClose()
}
Loading