Skip to content

Commit

Permalink
JVM support
Browse files Browse the repository at this point in the history
  • Loading branch information
SalomonBrys committed Dec 16, 2024
1 parent cc0a8ea commit a5aa4cc
Show file tree
Hide file tree
Showing 29 changed files with 637 additions and 70 deletions.
63 changes: 43 additions & 20 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,42 @@ permissions:
contents: read

jobs:
build:
uses: ./.github/workflows/gradle.yml
deploy:
needs: build
test:
uses: ./.github/workflows/test.yml
build-native:
name: Build native lib
strategy:
matrix:
include:
- target: publishAllPublicationsToSonatypeRepository
os: macos-latest
# FIXME: Our custom gradle plugin does not currently setup platform specific tasks
# - target: publishIosArm64PublicationToSonatypeRepository
# os: macos-latest
# - target: publishAndroidDebugPublicationToSonatypeRepository
# os: ubuntu-latest
# - target: publishAndroidReleasePublicationToSonatypeRepository
# os: ubuntu-latest
# - target: publishKotlinMultiplatformPublicationToSonatypeRepository
# os: ubuntu-latest
os: [macos-latest, ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@v1
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
- name: Set up Gradle
uses: gradle/actions/setup-gradle@v3
- name: Install cross-compiler
if: ${{ matrix.os == 'ubuntu-latest' }}
run: sudo apt install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
- name: Build native lib
run: |
./gradlew \
-PGITHUB_PUBLISH_TOKEN=${{ secrets.GITHUB_TOKEN }} \
:core:cmakeJvmBuild
- name: Upload build
uses: actions/upload-artifact@v4
with:
name: binaries-${{ matrix.os }}
path: core/build/binaries/desktop/sqlite/
deploy:
needs: [test, build-native]
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Validate Gradle Wrapper
Expand All @@ -39,20 +56,26 @@ jobs:
with:
java-version: '17'
distribution: 'temurin'

- name: Set up Gradle
uses: gradle/actions/setup-gradle@v3

- name: Download native binaries
uses: actions/download-artifact@v4
with:
path: core/binaries/desktop
merge-multiple: true
- name: Display downloaded files
run: ls -lR core/binaries/desktop
- name: Gradle publish
run: |
./gradlew \
${{ matrix.target }} \
-PGITHUB_PUBLISH_TOKEN="${{ secrets.GITHUB_TOKEN }}" \
-PsigningInMemoryKey="${{ secrets.SIGNING_KEY }}" \
-PsigningInMemoryKeyId="${{ secrets.SIGNING_KEY_ID }}" \
-PsigningInMemoryKeyPassword="${{ secrets.SIGNING_PASSWORD }}" \
-PcentralPortal.username="${{secrets.SONATYPE_USERNAME}}" \
-PcentralPortal.password="${{secrets.SONATYPE_PASSWORD}}"
-PcentralPortal.password="${{secrets.SONATYPE_PASSWORD}}" \
-Ppowersync.binaries.provided="true"
publishAllPublicationsToSonatypeRepository
# This will change Package.swift in Github packages to direct to new maven central KMMBridge zip file
call-kmmbridge-publish:
needs: deploy
Expand Down
File renamed without changes.
7 changes: 5 additions & 2 deletions PowerSyncKotlin/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import co.touchlab.faktory.artifactmanager.ArtifactManager
import co.touchlab.faktory.capitalized
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
import org.jetbrains.kotlin.ir.backend.js.compile
import java.net.URL
import java.security.MessageDigest

Expand Down Expand Up @@ -28,8 +29,10 @@ kotlin {
explicitApi()

targets.withType<KotlinNativeTarget> {
compilations.getByName("main") {
compilerOptions.options.freeCompilerArgs.add("-Xexport-kdoc")
compilations.named("main") {
compileTaskProvider {
compilerOptions.freeCompilerArgs.add("-Xexport-kdoc")
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions compose/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ kotlin {
publishLibraryVariants("release", "debug")
}

jvm()

iosX64()
iosArm64()
iosSimulatorArm64()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.powersync.compose

import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import com.powersync.DatabaseDriverFactory

@Composable
public actual fun rememberDatabaseDriverFactory(): DatabaseDriverFactory =
remember {
DatabaseDriverFactory()
}
8 changes: 6 additions & 2 deletions connectors/supabase/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,13 @@ kotlin {
publishLibraryVariants("release", "debug")
}

jvm()

targets.withType<KotlinNativeTarget> {
compilations.getByName("main") {
compilerOptions.options.freeCompilerArgs.add("-Xexport-kdoc")
compilations.named("main") {
compileTaskProvider {
compilerOptions.freeCompilerArgs.add("-Xexport-kdoc")
}
}
}

Expand Down
1 change: 1 addition & 0 deletions core/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
binaries/
151 changes: 145 additions & 6 deletions core/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import app.cash.sqldelight.core.capitalize
import com.powersync.plugins.sonatype.setupGithubRepository
import de.undercouch.gradle.tasks.download.Download
import org.gradle.internal.os.OperatingSystem
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget

plugins {
Expand All @@ -13,12 +15,12 @@ plugins {
alias(libs.plugins.mokkery)
}

val sqliteVersion = "3450000"
val sqliteVersion = "3450200"
val sqliteReleaseYear = "2024"

val sqliteSrcFolder =
project.layout.buildDirectory
.dir("interop/sqlite")
.dir("native/sqlite")
.get()

val downloadSQLiteSources by tasks.registering(Download::class) {
Expand Down Expand Up @@ -50,8 +52,13 @@ val unzipSQLiteSources by tasks.registering(Copy::class) {
val buildCInteropDef by tasks.registering {
dependsOn(unzipSQLiteSources)

val interopFolder =
project.layout.buildDirectory
.dir("interop/sqlite")
.get()

val cFile = sqliteSrcFolder.file("sqlite3.c").asFile
val defFile = sqliteSrcFolder.file("sqlite3.def").asFile
val defFile = interopFolder.file("sqlite3.def").asFile

doFirst {
defFile.writeText(
Expand All @@ -69,18 +76,21 @@ kotlin {
androidTarget {
publishLibraryVariants("release", "debug")
}
jvm()

iosX64()
iosArm64()
iosSimulatorArm64()

targets.withType<KotlinNativeTarget> {
compilations.getByName("main") {
compilerOptions.options.freeCompilerArgs.add("-Xexport-kdoc")
compilations.named("main") {
compileTaskProvider {
compilerOptions.freeCompilerArgs.add("-Xexport-kdoc")
}
cinterops.create("sqlite") {
val cInteropTask = tasks[interopProcessingTaskName]
cInteropTask.dependsOn(buildCInteropDef)
defFile =
definitionFile =
buildCInteropDef
.get()
.outputs.files.singleFile
Expand Down Expand Up @@ -118,6 +128,11 @@ kotlin {
implementation(libs.ktor.client.okhttp)
}

jvmMain.dependencies {
implementation(libs.ktor.client.okhttp)
implementation(libs.sqlite.jdbc)
}

iosMain.dependencies {
implementation(libs.ktor.client.ios)
}
Expand Down Expand Up @@ -159,6 +174,7 @@ android {
.get()
.toInt()

@Suppress("UnstableApiUsage")
externalNativeBuild {
cmake {
arguments.addAll(
Expand All @@ -177,6 +193,129 @@ android {
}
}

val os = OperatingSystem.current()
val binariesAreProvided = project.findProperty("powersync.binaries.provided") == "true"
val binariesFolder =
project.layout.buildDirectory
.dir("binaries/desktop")

val getBinaries = if (binariesAreProvided) {
// Binaries for all OS must be provided (manually or by the CI) in binaries/desktop

val verifyPowersyncBinaries = tasks.register("verifyPowersyncBinaries") {
val directory = projectDir.resolve("binaries/desktop")
val binaries = listOf(
directory.resolve("libpowersync-sqlite_aarch64.so"),
directory.resolve("libpowersync-sqlite_x64.so"),
directory.resolve("libpowersync-sqlite_aarch64.dylib"),
directory.resolve("libpowersync-sqlite_x64.dylib"),
directory.resolve("powersync-sqlite_x64.dll"),
)
doLast {
binaries.forEach {
if (!it.exists()) error("File $it does not exist")
if (!it.isFile) error("File $it is not a regular file")
}
}
outputs.files(*binaries.toTypedArray())
}
verifyPowersyncBinaries
} else {
// Building locally for the current OS

fun registerCMakeTasks(
suffix: String,
vararg defines: String,
): TaskProvider<Exec> {
val cmakeConfigure = tasks.register<Exec>("cmakeJvmConfigure${suffix.capitalize()}") {
dependsOn(unzipSQLiteSources)
group = "cmake"
workingDir = layout.buildDirectory.dir("cmake/$suffix").get().asFile
inputs.files(
"src/jvmMain/cpp",
"src/jvmNative/cpp",
sqliteSrcFolder,
)
outputs.dir(workingDir)
executable = "cmake"
args(listOf(file("src/jvmMain/cpp/CMakeLists.txt").absolutePath, "-DSUFFIX=$suffix", "-DCMAKE_BUILD_TYPE=Release") + defines.map { "-D$it" })
doFirst {
workingDir.mkdirs()
}
}

val cmakeBuild = tasks.register<Exec>("cmakeJvmBuild${suffix.capitalize()}") {
dependsOn(cmakeConfigure)
group = "cmake"
workingDir = layout.buildDirectory.dir("cmake/$suffix").get().asFile
inputs.files(
"src/jvmMain/cpp",
"src/jvmNative/cpp",
sqliteSrcFolder,
workingDir,
)
outputs.dir(workingDir.resolve(if (os.isWindows) "output/Release" else "output"))
executable = "cmake"
args("--build", ".", "--config", "Release")
}

return cmakeBuild
}

val cmakeJvmBuilds = when {
os.isMacOsX -> listOf(
registerCMakeTasks("aarch64", "CMAKE_OSX_ARCHITECTURES=arm64"),
registerCMakeTasks("x64", "CMAKE_OSX_ARCHITECTURES=x86_64"),
)
os.isLinux -> listOf(
registerCMakeTasks("aarch64", "CMAKE_C_COMPILER=aarch64-linux-gnu-gcc", "CMAKE_CXX_COMPILER=aarch64-linux-gnu-g++"),
registerCMakeTasks(
"x64", "CMAKE_C_COMPILER=x86_64-linux-gnu-gcc", "CMAKE_CXX_COMPILER=x86_64-linux-gnu-g++"),
)
os.isWindows -> listOf(
registerCMakeTasks("x64"),
)
else -> error("Unknown operating system: $os")
}

tasks.register<Copy>("cmakeJvmBuild") {
dependsOn(cmakeJvmBuilds)
group = "cmake"
from(cmakeJvmBuilds)
into(binariesFolder.map { it.dir("sqlite") })
}
}

val downloadPowersyncDesktopBinaries = tasks.register<Download>("downloadPowersyncDesktopBinaries") {
val coreVersion = libs.versions.powersync.core.get()
val linux = listOf(
"https://github.com/powersync-ja/powersync-sqlite-core/releases/download/v$coreVersion/libpowersync_aarch64.so",
"https://github.com/powersync-ja/powersync-sqlite-core/releases/download/v$coreVersion/libpowersync_x64.so",
)
val mac = listOf(
"https://github.com/powersync-ja/powersync-sqlite-core/releases/download/v$coreVersion/libpowersync_aarch64.dylib",
"https://github.com/powersync-ja/powersync-sqlite-core/releases/download/v$coreVersion/libpowersync_x64.dylib",
)
val windows = listOf(
"https://github.com/powersync-ja/powersync-sqlite-core/releases/download/v$coreVersion/powersync_x64.dll",
)
src(when {
binariesAreProvided -> linux + mac + windows
else -> when {
os.isLinux -> linux
os.isMacOsX -> mac
os.isWindows -> windows
else -> error("Unknown operating system: $os")
}
})
dest(binariesFolder.map { it.dir("powersync") })
onlyIfModified(true)
}

tasks.named<ProcessResources>(kotlin.jvm().compilations["main"].processResourcesTaskName) {
from(getBinaries, downloadPowersyncDesktopBinaries)
}

afterEvaluate {
val buildTasks =
tasks.matching {
Expand Down
2 changes: 1 addition & 1 deletion core/src/androidMain/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ set(BUILD_DIR ${CMAKE_SOURCE_DIR}/build)
add_library(
${PACKAGE_NAME}
SHARED
sqlite_bindings.cpp
../../jvmNative/cpp/sqlite_bindings.cpp
"${SQLITE3_SRC_DIR}/sqlite3.c"
)

Expand Down
1 change: 1 addition & 0 deletions core/src/androidMain/kotlin/BuildConfig.kt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
@Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
public actual object BuildConfig {
public actual val isDebug: Boolean
get() = com.powersync.BuildConfig.DEBUG
Expand Down
1 change: 1 addition & 0 deletions core/src/commonMain/kotlin/BuildConfig.kt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
@Suppress("EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING")
public expect object BuildConfig {
public val isDebug: Boolean
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,12 @@ internal object InternalSchema : SqlSchema<QueryResult.AsyncValue<Unit>> {
override val version: Long
get() = 1

override fun create(driver: SqlDriver): QueryResult.AsyncValue<Unit> =
QueryResult.AsyncValue {}
override fun create(driver: SqlDriver): QueryResult.AsyncValue<Unit> = QueryResult.AsyncValue {}

override fun migrate(
driver: SqlDriver,
oldVersion: Long,
newVersion: Long,
vararg callbacks: AfterVersion,
): QueryResult.AsyncValue<Unit> =
QueryResult.AsyncValue {}
): QueryResult.AsyncValue<Unit> = QueryResult.AsyncValue {}
}
Loading

0 comments on commit a5aa4cc

Please sign in to comment.