diff --git a/examples/duckdb-0.9-c/.gitignore b/examples/duckdb-0.9-c/.gitignore new file mode 100644 index 00000000..40b3ca8b --- /dev/null +++ b/examples/duckdb-0.9-c/.gitignore @@ -0,0 +1,6 @@ +/rootfs/ +/rootfs.cpio +/run-qemu* +/run-fc* +/kraft-run-* +/fc*.json diff --git a/examples/duckdb-0.9-c/Dockerfile b/examples/duckdb-0.9-c/Dockerfile new file mode 100644 index 00000000..ca591092 --- /dev/null +++ b/examples/duckdb-0.9-c/Dockerfile @@ -0,0 +1,39 @@ +FROM --platform=linux/x86_64 debian:bookworm AS build + +RUN set -xe; \ + apt -yqq update; \ + apt -yqq install \ + wget \ + ca-certificates \ + build-essential \ + unzip \ + ; + +ARG DUCKDB_VERSION=0.9.1 + +WORKDIR /src + +RUN set -xe; \ + wget https://github.com/duckdb/duckdb/releases/download/v${DUCKDB_VERSION}/libduckdb-linux-amd64.zip; \ + unzip -q libduckdb-linux-amd64.zip; \ + mv libduckdb.so /usr/local/lib/; \ + ldconfig /usr/local/lib/libduckdb.so \ + ; + +COPY ./main.c /src/main.c + +RUN set -xe; \ + gcc -Wall -I. -o /main /src/main.c -lduckdb + +FROM scratch + +COPY --from=build /main /main +COPY --from=build /usr/local/lib/libduckdb.so /usr/local/lib/libduckdb.so +COPY --from=build /lib/x86_64-linux-gnu/libc.so.6 /lib/x86_64-linux-gnu/libc.so.6 +COPY --from=build /lib/x86_64-linux-gnu/libgcc_s.so.1 /lib/x86_64-linux-gnu/libgcc_s.so.1 +COPY --from=build /lib/x86_64-linux-gnu/libpthread.so.0 /lib/x86_64-linux-gnu/libpthread.so.0 +COPY --from=build /lib/x86_64-linux-gnu/libdl.so.2 /lib/x86_64-linux-gnu/libdl.so.2 +COPY --from=build /lib/x86_64-linux-gnu/libstdc++.so.6 /lib/x86_64-linux-gnu/libstdc++.so.6 +COPY --from=build /lib/x86_64-linux-gnu/libm.so.6 /lib/x86_64-linux-gnu/libm.so.6 +COPY --from=build /lib64/ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2 +COPY --from=build /etc/ld.so.cache /etc/ld.so.cache diff --git a/examples/duckdb-0.9-c/Kraftfile b/examples/duckdb-0.9-c/Kraftfile new file mode 100644 index 00000000..02f0cbc5 --- /dev/null +++ b/examples/duckdb-0.9-c/Kraftfile @@ -0,0 +1,9 @@ +spec: v0.6 + +name: duckdb-c + +runtime: index.unikraft.io/unikraft.org/base:latest + +rootfs: ./Dockerfile + +cmd: ["/main"] diff --git a/examples/duckdb-0.9-c/Makefile b/examples/duckdb-0.9-c/Makefile new file mode 100644 index 00000000..e0f42620 --- /dev/null +++ b/examples/duckdb-0.9-c/Makefile @@ -0,0 +1,3 @@ +IMAGE_NAME = unikraft-duckdb-c + +include ../../utils/bincompat/docker.Makefile diff --git a/examples/duckdb-0.9-c/README.md b/examples/duckdb-0.9-c/README.md new file mode 100644 index 00000000..1ad22c9a --- /dev/null +++ b/examples/duckdb-0.9-c/README.md @@ -0,0 +1,24 @@ +# DuckDB C Example + +This directory contains a simple C example using the [DuckDB](https://duckdb.org) library running with Unikraft in binary compatibility mode. +The C program is extracted from [DuckDB examples](https://github.com/duckdb/duckdb/blob/main/examples/embedded-c/main.c) and it creates and uses a test database. + +Follow the instructions in the common `../README.md` file to set up and configure the application. + +## Quick Run + +Use `kraft` to run the image: + +```console +kraft run -M 128M +``` + +Once executed, it will print out information from the created database: + +```console +``` + +## Scripted Run + +Use the scripted runs, detailed in the common `../README.md`. +Running the scripts will print out information ame as above. diff --git a/examples/duckdb-0.9-c/config.yaml b/examples/duckdb-0.9-c/config.yaml new file mode 100644 index 00000000..41b7e808 --- /dev/null +++ b/examples/duckdb-0.9-c/config.yaml @@ -0,0 +1,3 @@ +networking: False +accel: True +memory: 256 diff --git a/examples/duckdb-0.9-c/main.c b/examples/duckdb-0.9-c/main.c new file mode 100644 index 00000000..69fa0e04 --- /dev/null +++ b/examples/duckdb-0.9-c/main.c @@ -0,0 +1,52 @@ +/* https://github.com/duckdb/duckdb/blob/main/examples/embedded-c/main.c */ + +#include "duckdb.h" +#include + +int main() { + duckdb_database db = NULL; + duckdb_connection con = NULL; + duckdb_result result; + + if (duckdb_open(NULL, &db) == DuckDBError) { + fprintf(stderr, "Failed to open database\n"); + goto cleanup; + } + if (duckdb_connect(db, &con) == DuckDBError) { + fprintf(stderr, "Failed to open connection\n"); + goto cleanup; + } + if (duckdb_query(con, "CREATE TABLE integers(i INTEGER, j INTEGER);", NULL) == DuckDBError) { + fprintf(stderr, "Failed to query database\n"); + goto cleanup; + } + if (duckdb_query(con, "INSERT INTO integers VALUES (3, 4), (5, 6), (7, NULL);", NULL) == DuckDBError) { + fprintf(stderr, "Failed to query database\n"); + goto cleanup; + } + if (duckdb_query(con, "SELECT * FROM integers", &result) == DuckDBError) { + fprintf(stderr, "Failed to query database\n"); + goto cleanup; + } + // print the names of the result + idx_t row_count = duckdb_row_count(&result); + idx_t column_count = duckdb_column_count(&result); + for (size_t i = 0; i < column_count; i++) { + printf("%s ", duckdb_column_name(&result, i)); + } + printf("\n"); + // print the data of the result + for (size_t row_idx = 0; row_idx < row_count; row_idx++) { + for (size_t col_idx = 0; col_idx < column_count; col_idx++) { + char *val = duckdb_value_varchar(&result, col_idx, row_idx); + printf("%s ", val); + duckdb_free(val); + } + printf("\n"); + } + // duckdb_print_result(result); +cleanup: + duckdb_destroy_result(&result); + duckdb_disconnect(&con); + duckdb_close(&db); +}