Skip to content

[proposal] Change compiler/linker options, implement docker build, fix error handling and more #236

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
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
3 changes: 3 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.gradle
.idea
build
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
gradlew text eol=lf
119 changes: 119 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# Define project root inside build container
ARG SOURCE_ROOT=/usr/src/postgres-native-sqldelight-driver

# Define builder distro:
# "ubuntu" (ubuntu:noble, default)
# "alpine" (alpine:3)
ARG BUILDER_DISTRO=ubuntu

# Define runtime distro:
# "ubuntu" (ubuntu:noble, default)
# "alpine" (alpine:3)
ARG RUNTIME_DISTRO=ubuntu

################################################################################
# STAGE 1: setup builders
################################################################################

# Kotlin/Native prebuilt compiler is available for x86_64 Linux only, so Use "linux/amd64" platform for base builder image
FROM --platform=linux/amd64 ubuntu:noble AS ubuntu-builder-base
RUN \
--mount=type=cache,sharing=locked,target=/var/lib/apt/lists \
--mount=type=cache,sharing=locked,target=/var/cache/apt \
apt-get update && \
apt install -y \
git \
cmake \
pkgconf \
build-essential \
crossbuild-essential-arm64 \
openjdk-17-jdk-headless

FROM ubuntu-builder-base AS ubuntu-builder-base-amd64
RUN \
--mount=type=cache,sharing=locked,target=/var/lib/apt/lists \
--mount=type=cache,sharing=locked,target=/var/cache/apt \
apt-get install --no-install-recommends -y libpq-dev:amd64

FROM ubuntu-builder-base AS ubuntu-builder-base-arm64
ADD ubuntu-arm64-sources.list /etc/apt/sources.list.d/
RUN \
--mount=type=cache,sharing=locked,target=/var/lib/apt/lists \
--mount=type=cache,sharing=locked,target=/var/cache/apt \
apt-get update && \
dpkg --add-architecture arm64 && \
apt-get install --no-install-recommends -y libpq-dev:arm64

FROM ubuntu-builder-base-${TARGETARCH} AS ubuntu-builder-base

FROM --platform=linux/amd64 alpine:3 AS alpine-builder-base-amd64
# TODO
RUN echo "Not implemented: dependencies for building under alpine should be resolved, use ubuntu builder instead" && exit 1
RUN apk update && apk add --no-cache libstdc++ libpq-dev openjdk17-jdk

FROM alpine-builder-base-${TARGETARCH} AS alpine-builder-base

FROM ${BUILDER_DISTRO}-builder-base AS builder

################################################################################
# STAGE 2: add project sources and configure gradle build
################################################################################

FROM builder AS sources
ARG SOURCE_ROOT
WORKDIR ${SOURCE_ROOT}
ADD . .
RUN chmod +x ./gradlew

FROM sources AS gradlew
ENV GRADLE_OPTS="-Dorg.gradle.daemon=false"
RUN \
--mount=type=cache,sharing=private,target=/root/.konan \
--mount=type=cache,sharing=private,target=/root/.gradle \
./gradlew

################################################################################
# STAGE 3: compile binaries
################################################################################

FROM gradlew AS test-binaries-amd64
ARG SOURCE_ROOT
RUN ./gradlew :testing:linuxX64TestBinaries --info --stacktrace

FROM gradlew AS test-binaries-arm64
ARG SOURCE_ROOT
RUN ./gradlew :testing:linuxArm64TestBinaries --info --stacktrace

FROM test-binaries-${TARGETARCH} AS test-binaries

################################################################################
# STAGE 4: copy binaries & prepare runtime
################################################################################

# This target doesn't use "--platform" argument, so the target image will be multiarch
FROM ubuntu:noble AS ubuntu-test-runtime-base
RUN apt-get update && apt-get install --no-install-recommends -y libpq-dev file

FROM alpine:3 AS alpine-test-runtime-base
RUN \
apk update && \
apk add --no-cache \
gcompat g++ libpq-dev file

FROM ${RUNTIME_DISTRO}-test-runtime-base AS test-runtime-base
WORKDIR /usr/local/bin

FROM --platform=linux/amd64 test-runtime-base AS test-runtime-amd64
ENV KOTLIN_NATIVE_TARGET=linuxX64

FROM --platform=linux/arm64 test-runtime-base AS test-runtime-arm64
ENV KOTLIN_NATIVE_TARGET=linuxArm64

FROM test-runtime-${TARGETARCH} AS test-runtime
ARG SOURCE_ROOT
COPY --from=test-binaries ${SOURCE_ROOT}/testing/build/bin/${KOTLIN_NATIVE_TARGET}/debugTest/test.kexe test.kexe
ENTRYPOINT [ "sh", "-c" ]
CMD [ "./test.kexe" ]

# Default target
FROM test-runtime
46 changes: 44 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,54 @@ For compilers to find libpq you may need to set:
For installation using homebrew, the default path is already added.

### Testing

#### Using local machine
If you install libpq with homebrew, it will install the platform-specific artifact.

To test other platforms, eg. linux x64 on macOS, you need to install the platform-specific libpq of linux x64 too.

To start the postgres instance, you can use docker:
```sh
docker run -e POSTGRES_PASSWORD=password -p 5432:5432 postgres
```

#### Using Docker

To build and test project run this commands:

```sh
docker compose up ubuntu-test-runtime
docker compose up alpine-test-runtime
```

... and the same for [prebuilt images](https://hub.docker.com/r/myshkouski/kotlin-native-postgres-driver-testing/tags), on either `linux/amd64` or `linux/arm64` hosts.
```sh
docker compose up ubuntu-test-runtime-prebuilt
docker compose up alpine-test-runtime-prebuilt
```

The output of `debugTest` binary should be:
```
alpine-test-runtime-1 | [==========] Running 5 tests from 1 test cases.
alpine-test-runtime-1 | [----------] Global test environment set-up.
alpine-test-runtime-1 | [----------] 5 tests from app.softwork.sqldelight.postgresdriver.PostgresNativeDriverTest
alpine-test-runtime-1 | [ RUN ] app.softwork.sqldelight.postgresdriver.PostgresNativeDriverTest.simpleTest
alpine-test-runtime-1 | [ OK ] app.softwork.sqldelight.postgresdriver.PostgresNativeDriverTest.simpleTest (52 ms)
alpine-test-runtime-1 | [ RUN ] app.softwork.sqldelight.postgresdriver.PostgresNativeDriverTest.wrongCredentials
alpine-test-runtime-1 | [ OK ] app.softwork.sqldelight.postgresdriver.PostgresNativeDriverTest.wrongCredentials (5015 ms)
alpine-test-runtime-1 | [ RUN ] app.softwork.sqldelight.postgresdriver.PostgresNativeDriverTest.copyTest
alpine-test-runtime-1 | [ OK ] app.softwork.sqldelight.postgresdriver.PostgresNativeDriverTest.copyTest (16 ms)
alpine-test-runtime-1 | [ RUN ] app.softwork.sqldelight.postgresdriver.PostgresNativeDriverTest.remoteListenerTest
alpine-test-runtime-1 | [ OK ] app.softwork.sqldelight.postgresdriver.PostgresNativeDriverTest.remoteListenerTest (6016 ms)
alpine-test-runtime-1 | [ RUN ] app.softwork.sqldelight.postgresdriver.PostgresNativeDriverTest.localListenerTest
alpine-test-runtime-1 | [ OK ] app.softwork.sqldelight.postgresdriver.PostgresNativeDriverTest.localListenerTest (7 ms)
alpine-test-runtime-1 | [----------] 5 tests from app.softwork.sqldelight.postgresdriver.PostgresNativeDriverTest (11109 ms total)
alpine-test-runtime-1 |
alpine-test-runtime-1 | [----------] Global test environment tear-down
alpine-test-runtime-1 | [==========] 5 tests from 1 test cases ran. (11109 ms total)
alpine-test-runtime-1 | [ PASSED ] 5 tests.
alpine-test-runtime-1 exited with code 0
```

#### TODO:
- [ ] add container for zero-config compiling dependent projects
- [ ] setup alpine-based build container

10 changes: 0 additions & 10 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
plugins {
id("io.github.gradle-nexus.publish-plugin")
id("org.jetbrains.dokka")
}

tasks.dokkaHtmlMultiModule {
includes.from("README.md")
}

nexusPublishing {
this.repositories {
sonatype {
nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/"))
snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/"))
}
}
}
73 changes: 73 additions & 0 deletions compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
version: "3.8"

x-services:
test-runtime: &test-runtime
environment:
POSTGRES_HOST: postgres
depends_on:
postgres:
condition: service_healthy
test-runtime-info-cmd: &test-runtime-info-cmd
command: [ "uname -a", "printenv; cat /etc/*release*; ldconfig -p | grep libpq.so; ls -lh; file *;" ]

services:
postgres:
image: postgres:16-alpine
command: ["postgres", "-c", "log_statement=all", "-c", "log_destination=stderr"]
environment:
POSTGRES_PASSWORD: password
ports:
- "127.0.0.1:5432:5432"
healthcheck:
test: "pg_isready -U postgres"
interval: 10s
timeout: 3s
retries: 3
ubuntu-test-runtime:
<<: *test-runtime
build:
args:
RUNTIME_DISTRO: ubuntu
tags:
- myshkouski/kotlin-native-postgres-driver-testing:latest
- myshkouski/kotlin-native-postgres-driver-testing:ubuntu
alpine-test-runtime:
<<: *test-runtime
build:
args:
RUNTIME_DISTRO: alpine
tags:
- myshkouski/kotlin-native-postgres-driver-testing:alpine
ubuntu-test-runtime-info:
extends:
service: ubuntu-test-runtime
<<: *test-runtime-info-cmd
alpine-test-runtime-info:
extends:
service: alpine-test-runtime
<<: *test-runtime-info-cmd
ubuntu-test-runtime-prebuilt:
<<: *test-runtime
image: myshkouski/kotlin-native-postgres-driver-testing
alpine-test-runtime-prebuilt:
<<: *test-runtime
image: myshkouski/kotlin-native-postgres-driver-testing:alpine
ubuntu-test-runtime-prebuilt-info:
extends:
service: ubuntu-test-runtime-prebuilt
<<: *test-runtime-info-cmd
alpine-test-runtime-prebuilt-info:
extends:
service: alpine-test-runtime-prebuilt
<<: *test-runtime-info-cmd
ubuntu-sources:
build:
target: gradlew
args:
BUILDER_DISTRO: ubuntu
# TODO: not implemented, see Dockerfile for details
# alpine-sources:
# build:
# target: gradlew
# args:
# BUILDER_DISTRO: alpine
3 changes: 2 additions & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ org.gradle.jvmargs=-Xmx2048m
org.gradle.configuration-cache=true
org.gradle.configureondemand=true

group=app.softwork
group=io.github.myshkouski.sqldelight
version=0.0.12
33 changes: 24 additions & 9 deletions gradle/build-logic/src/main/kotlin/publish.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ plugins {

val emptyJar by tasks.registering(Jar::class) { }

val Project.isSnapshotVersion: Boolean
get() = version.toString().endsWith("SNAPSHOT")

publishing {
publications.configureEach {
this as MavenPublication
Expand All @@ -34,23 +37,35 @@ publishing {
name.set("Philip Wedemann")
email.set("mybztg+mavencentral@icloud.com")
}
developer {
id.set("Myshkouski")
name.set("Alexei Myshkouski")
email.set("alexeimyshkouski@gmail.com")
}
}
scm {
connection.set("scm:git://github.com/hfhbd/SqlDelightNativePostgres.git")
developerConnection.set("scm:git://github.com/hfhbd/SqlDelightNativePostgres.git")
url.set("https://github.com/hfhbd/SqlDelightNativePostgres")
connection.set("scm:git://github.com/Myshkouski/postgres-native-sqldelight.git")
developerConnection.set("scm:git://github.com/Myshkouski/postgres-native-sqldelight.git")
url.set("https://github.com/Myshkouski/postgres-native-sqldelight")
}
}
}

repositories {
maven {
name = "sonatype"
url = if (isSnapshotVersion) {
uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")
} else {
uri("https://s01.oss.sonatype.org/content/repositories/releases/")
}
credentials(PasswordCredentials::class)
}
}
}

signing {
val signingKey: String? by project
val signingPassword: String? by project
signingKey?.let {
useInMemoryPgpKeys(String(Base64.getDecoder().decode(it)).trim(), signingPassword)
sign(publishing.publications)
}
sign(publishing.publications)
}

// https://youtrack.jetbrains.com/issue/KT-46466
Expand Down
Empty file modified gradlew
100755 → 100644
Empty file.
10 changes: 5 additions & 5 deletions postgres-native-sqldelight-driver/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ kotlin {
}
}

fun KotlinNativeTarget.config() {
fun KotlinNativeTarget.configure() {
compilations.named("main") {
cinterops {
register("libpq") {
Expand All @@ -26,10 +26,10 @@ kotlin {
}
}

macosArm64 { config() }
macosX64 { config() }
linuxX64 { config() }
linuxArm64 { config() }
linuxX64 { configure() }
linuxArm64 { configure() }
macosX64 { configure() }
macosArm64 { configure() }
// mingwX64 { config() }

sourceSets {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,8 @@ public class PostgresNativeDriver(
@ExperimentalForeignApi
private fun CPointer<PGconn>?.error(): String {
val errorMessage = PQerrorMessage(this)!!.toKString()
PQfinish(this)
// TODO("find out why this lien causes segmentation fault")
// PQfinish(this)
return errorMessage
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,16 @@ package = libpq
#staticLibraries = libpq.a
#libraryPaths = /opt/homebrew/opt/libpq/lib

compilerOpts = -I/home/linuxbrew/.linuxbrew/opt/libpq/include -I/opt/homebrew/opt/libpq/include -I/usr/local/opt/libpq/include
linkerOpts = -L/home/linuxbrew/.linuxbrew/opt/libpq/lib -L/opt/homebrew/opt/libpq/lib -L/usr/local/opt/libpq/lib -lpq
linkerOpts = -lpq

#linkerOpts.linux = -L/usr/lib
#linkerOpts.linux_x64 = -L/usr/lib/x86_64-linux-gnu
# No docs about linux_arm64? linux_aarch64?
#linkerOpts.linux_??? = -L/usr/lib/aarch64-linux-gnu
# Since Koltin/Native compiler for aarch64 is available on linux_x86_64 only, share /usr/lib/x86_64-linux-gnu between x86_64 and aarch64
linkerOpts.linux = -L/usr/lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/aarch64-linux-gnu

linkerOpts.osx = -L/opt/homebrew/opt/libpq/lib -L/usr/local/opt/libpq/lib

compilerOpts.linux = -I/usr/include/postgresql
compilerOpts.osx = -I/opt/homebrew/opt/libpq/include -I/usr/local/opt/libpq/include
Loading