Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ on:
env:
CARGO_TERM_COLOR: always
MIX_ENV: test
ECTO_LIBSQL_BUILD: "true"

jobs:
rust-checks:
Expand Down
81 changes: 81 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
name: Build Precompiled NIFs

on:
push:
branches:
- main
paths:
- "native/**"
- ".github/workflows/release.yml"
tags:
- "v*"
pull_request:
paths:
- ".github/workflows/release.yml"
workflow_dispatch:

permissions:
contents: write

jobs:
build_release:
name: NIF ${{ matrix.nif }} - ${{ matrix.job.target }} (${{ matrix.job.os }})
runs-on: ${{ matrix.job.os }}
strategy:
fail-fast: false
matrix:
nif: ["2.15"]
job:
- { target: aarch64-apple-darwin, os: macos-15 }
- { target: x86_64-apple-darwin, os: macos-15-intel }
- { target: aarch64-unknown-linux-gnu, os: ubuntu-24.04, use-cross: true }
- { target: aarch64-unknown-linux-musl, os: ubuntu-24.04, use-cross: true }
- { target: x86_64-unknown-linux-gnu, os: ubuntu-24.04 }
- { target: x86_64-unknown-linux-musl, os: ubuntu-24.04, use-cross: true }

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Extract project version
shell: bash
run: |
# Extract version from mix.exs @version attribute
VERSION=$(sed -n 's/^[[:space:]]*@version "\(.*\)"/\1/p' mix.exs | head -n1)
if [ -z "$VERSION" ]; then
echo "::error::Failed to extract version from mix.exs"
exit 1
fi
echo "PROJECT_VERSION=$VERSION" >> $GITHUB_ENV
Comment thread
coderabbitai[bot] marked this conversation as resolved.

Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.job.target }}

- name: Build the project
id: build-crate
uses: philss/rustler-precompiled-action@v1.1.4
env:
CARGO_BUILD_TARGET: ${{ matrix.job.target }}
with:
project-name: ecto_libsql
project-version: ${{ env.PROJECT_VERSION }}
target: ${{ matrix.job.target }}
nif-version: ${{ matrix.nif }}
use-cross: ${{ matrix.job.use-cross }}
cross-version: "from-source"
project-dir: "native/ecto_libsql"

- name: Artifact upload
uses: actions/upload-artifact@v4
with:
name: ${{ steps.build-crate.outputs.file-name }}
path: ${{ steps.build-crate.outputs.file-path }}

- name: Publish archives and packages
uses: softprops/action-gh-release@v2
with:
files: |
${{ steps.build-crate.outputs.file-path }}
if: startsWith(github.ref, 'refs/tags/')
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ resolver = "2"

members = ["native/ecto_libsql"]
exclude = ["native/ecto_libsql/fuzz"]

[profile.release]
lto = "thin"
22 changes: 20 additions & 2 deletions lib/ecto_libsql/native.ex
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,27 @@ defmodule EctoLibSql.Native do

"""

use Rustler,
mix_config = Mix.Project.config()
version = mix_config[:version]
github_url = mix_config[:package][:links]["GitHub"]
mode = if Mix.env() in [:dev, :test], do: :debug, else: :release

use RustlerPrecompiled,
otp_app: :ecto_libsql,
crate: :ecto_libsql
crate: "ecto_libsql",
version: version,
base_url: "#{github_url}/releases/download/v#{version}",
targets: ~w(
aarch64-apple-darwin
aarch64-unknown-linux-gnu
aarch64-unknown-linux-musl
x86_64-apple-darwin
x86_64-unknown-linux-gnu
x86_64-unknown-linux-musl
),
nif_versions: ["2.15"],
mode: mode,
force_build: System.get_env("ECTO_LIBSQL_BUILD") in ["1", "true"]

# Raw NIF functions - implemented in Rust (native/ecto_libsql/src/lib.rs)
# These all raise :nif_not_loaded errors until the NIF is loaded
Expand Down
8 changes: 6 additions & 2 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ defmodule EctoLibSql.MixProject do

@version "0.8.9"
@source_url "https://github.com/ocean/ecto_libsql"
@dev? String.ends_with?(@version, "-dev")
@force_build? System.get_env("ECTO_LIBSQL_BUILD") in ["1", "true"]

def project do
[
Expand Down Expand Up @@ -55,7 +57,8 @@ defmodule EctoLibSql.MixProject do
{:ecto_sql, "~> 3.11"},
{:ex_doc, "~> 0.31", only: :dev, runtime: false},
{:jason, "~> 1.4"},
{:rustler, "~> 0.37.1"},
{:rustler, "~> 0.37.1", optional: not (@dev? or @force_build?)},
{:rustler_precompiled, "~> 0.8"},
{:sobelow, "~> 0.13", only: [:dev, :test], runtime: false},
{:stream_data, "~> 1.0", only: [:dev, :test]}
]
Expand All @@ -64,7 +67,8 @@ defmodule EctoLibSql.MixProject do
defp package() do
[
name: "ecto_libsql",
files: ~w(lib priv .formatter.exs mix.exs README.md LICENSE CHANGELOG.md USAGE.md native),
files:
~w(lib priv .formatter.exs mix.exs README.md LICENSE CHANGELOG.md USAGE.md ECTO_MIGRATION_GUIDE.md SECURITY.md native checksum-*.exs),
licenses: ["Apache-2.0"],
links: %{
"GitHub" => @source_url,
Expand Down
2 changes: 2 additions & 0 deletions mix.lock
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
%{
"bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"},
"castore": {:hex, :castore, "1.0.17", "4f9770d2d45fbd91dcf6bd404cf64e7e58fed04fadda0923dc32acca0badffa2", [:mix], [], "hexpm", "12d24b9d80b910dd3953e165636d68f147a31db945d2dcb9365e441f8b5351e5"},
"credo": {:hex, :credo, "1.7.16", "a9f1389d13d19c631cb123c77a813dbf16449a2aebf602f590defa08953309d4", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "d0562af33756b21f248f066a9119e3890722031b6d199f22e3cf95550e4f1579"},
"db_connection": {:hex, :db_connection, "2.9.0", "a6a97c5c958a2d7091a58a9be40caf41ab496b0701d21e1d1abff3fa27a7f371", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "17d502eacaf61829db98facf6f20808ed33da6ccf495354a41e64fe42f9c509c"},
"decimal": {:hex, :decimal, "2.3.0", "3ad6255aa77b4a3c4f818171b12d237500e63525c2fd056699967a3e7ea20f62", [:mix], [], "hexpm", "a4d66355cb29cb47c3cf30e71329e58361cfcb37c34235ef3bf1d7bf3773aeac"},
Expand All @@ -16,6 +17,7 @@
"makeup_erlang": {:hex, :makeup_erlang, "1.0.3", "4252d5d4098da7415c390e847c814bad3764c94a814a0b4245176215615e1035", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "953297c02582a33411ac6208f2c6e55f0e870df7f80da724ed613f10e6706afd"},
"nimble_parsec": {:hex, :nimble_parsec, "1.4.2", "8efba0122db06df95bfaa78f791344a89352ba04baedd3849593bfce4d0dc1c6", [:mix], [], "hexpm", "4b21398942dda052b403bbe1da991ccd03a053668d147d53fb8c4e0efe09c973"},
"rustler": {:hex, :rustler, "0.37.1", "721434020c7f6f8e1cdc57f44f75c490435b01de96384f8ccb96043f12e8a7e0", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "24547e9b8640cf00e6a2071acb710f3e12ce0346692e45098d84d45cdb54fd79"},
"rustler_precompiled": {:hex, :rustler_precompiled, "0.8.4", "700a878312acfac79fb6c572bb8b57f5aae05fe1cf70d34b5974850bbf2c05bf", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:rustler, "~> 0.23", [hex: :rustler, repo: "hexpm", optional: true]}], "hexpm", "3b33d99b540b15f142ba47944f7a163a25069f6d608783c321029bc1ffb09514"},
"sobelow": {:hex, :sobelow, "0.14.1", "2f81e8632f15574cba2402bcddff5497b413c01e6f094bc0ab94e83c2f74db81", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "8fac9a2bd90fdc4b15d6fca6e1608efb7f7c600fa75800813b794ee9364c87f2"},
"stream_data": {:hex, :stream_data, "1.2.0", "58dd3f9e88afe27dc38bef26fce0c84a9e7a96772b2925c7b32cd2435697a52b", [:mix], [], "hexpm", "eb5c546ee3466920314643edf68943a5b14b32d1da9fe01698dc92b73f89a9ed"},
"telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"},
Expand Down
20 changes: 20 additions & 0 deletions native/ecto_libsql/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Cross-compilation configuration for rustler_precompiled NIF builds.
#
# macOS: Use dynamic lookup for Erlang NIF symbols (resolved at load time).
# musl: Disable static CRT linking for compatibility with BEAM's dynamic loader.

[target.'cfg(target_os = "macos")']
rustflags = [
"-C", "link-arg=-undefined",
"-C", "link-arg=dynamic_lookup",
]

[target.x86_64-unknown-linux-musl]
rustflags = [
"-C", "target-feature=-crt-static",
]

[target.aarch64-unknown-linux-musl]
rustflags = [
"-C", "target-feature=-crt-static",
]
2 changes: 1 addition & 1 deletion native/ecto_libsql/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ crate-type = ["cdylib", "rlib"]

[dependencies]
libsql = { version = "0.9.29", features = ["encryption", "replication"] }
rustler = "0.37.0"
rustler = { version = "0.37.1", default-features = false, features = ["derive", "nif_version_2_15"] }
tokio = "1.45.1"
uuid = "1.17.0"
bytes = "1.5"
Expand Down
Loading