diff --git a/.github/workflows/binaries.yml b/.github/workflows/binaries.yml new file mode 100644 index 0000000..a1469bb --- /dev/null +++ b/.github/workflows/binaries.yml @@ -0,0 +1,52 @@ +name: NIF binaries + +on: + push: + branches: + - main + paths: + - "native/**" + - ".github/workflows/binaries.yml" + tags: + - "*" + pull_request: + paths: + - ".github/workflows/binaries.yml" + workflow_dispatch: + +jobs: + build_binary: + name: ${{ matrix.job.target }} / ${{ matrix.job.os }} + runs-on: ${{ matrix.job.os }} + permissions: + contents: write + strategy: + fail-fast: false + matrix: + nif_version: ["2.16"] + job: + - { target: x86_64-apple-darwin , os: macos-12 } + - { target: x86_64-pc-windows-gnu , os: windows-2022 } + - { target: x86_64-unknown-linux-gnu , os: ubuntu-22.04 } + + steps: + - uses: actions/checkout@v4 + - run: rustup target add ${{ matrix.job.target }} + - run: echo "PROJECT_VERSION=$(sed -n 's/^ @version "\(.*\)"/\1/p' mix.exs | head -n1)" >> $GITHUB_ENV + + - uses: philss/rustler-precompiled-action@v1.1.1 + id: precompile + with: + project-dir: "native/candlex" + project-name: candlex + project-version: ${{ env.PROJECT_VERSION }} + target: ${{ matrix.job.target }} + nif-version: ${{ matrix.nif_version }} + # use-cross: false doesn't work + # I think because of https://github.com/actions/runner/issues/1173 + use-cross: null + + - uses: softprops/action-gh-release@v1 + with: + files: ${{ steps.precompile.outputs.file-path }} + if: startsWith(github.ref, 'refs/tags/') diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d42a1bc..c06aff8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,9 +4,12 @@ on: push: branches: - main + jobs: main: runs-on: ubuntu-latest + env: + CANDLE_BUILD: true strategy: fail-fast: false matrix: diff --git a/README.md b/README.md index b9fd3f0..447ed7b 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,17 @@ Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_do and published on [HexDocs](https://hexdocs.pm). Once published, the docs can be found at . +## Releasing + +To publish a new version of this package: + +1. Update `@version` in `mix.exs`. +1. Create and push a new tag. +1. Wait for the `binaries.yml` GitHub workflow to build all the binaries. +1. Generate checksums locally. +1. Publish the release from draft in GitHub. +1. Publish package to Hex. + ## License Copyright 2023 Mimiquate diff --git a/lib/candlex/native.ex b/lib/candlex/native.ex index 4ccc8d3..1edf9f4 100644 --- a/lib/candlex/native.ex +++ b/lib/candlex/native.ex @@ -1,7 +1,20 @@ defmodule Candlex.Native do @moduledoc false - use Rustler, otp_app: :candlex, features: Application.compile_env(:candlex, :crate_features, []) + version = Mix.Project.config()[:version] + source_url = "https://github.com/mimiquate/candlex" + + use RustlerPrecompiled, + otp_app: :candlex, + features: Application.compile_env(:candlex, :crate_features, []), + base_url: "#{source_url}/releases/download/v#{version}", + force_build: System.get_env("CANDLE_BUILD") in ["1", "true"], + version: version, + targets: [ + "x86_64-apple-darwin", + "x86_64-pc-windows-gnu", + "x86_64-unknown-linux-gnu" + ] # Rustler will override all the below stub functions with real NIFs def from_binary(_binary, _dtype, _shape, _device), do: error() diff --git a/mix.exs b/mix.exs index dbd1ec4..a81dc3b 100644 --- a/mix.exs +++ b/mix.exs @@ -33,10 +33,11 @@ defmodule Candlex.MixProject do defp deps do [ {:nx, "~> 0.6.2"}, - {:rustler, "~> 0.30.0"}, + {:rustler_precompiled, "~> 0.7.0"}, # Dev - {:ex_doc, "~> 0.30.9", only: :dev, runtime: false} + {:ex_doc, "~> 0.30.9", only: :dev, runtime: false}, + {:rustler, "~> 0.30.0", optional: true} ] end @@ -50,7 +51,16 @@ defmodule Candlex.MixProject do defp package do [ - files: ["lib", "native", "priv", ".formatter.exs", "mix.exs", "README.md", "LICENSE"], + files: [ + "lib", + "native", + "priv", + ".formatter.exs", + "mix.exs", + "README.md", + "LICENSE", + "checksum-*.exs" + ], licenses: ["Apache-2.0"], links: %{ "GitHub" => @source_url diff --git a/mix.lock b/mix.lock index 5e8ba96..aff8a25 100644 --- a/mix.lock +++ b/mix.lock @@ -1,4 +1,5 @@ %{ + "castore": {:hex, :castore, "1.0.4", "ff4d0fb2e6411c0479b1d965a814ea6d00e51eb2f58697446e9c41a97d940b28", [:mix], [], "hexpm", "9418c1b8144e11656f0be99943db4caf04612e3eaecefb5dae9a2a87565584f8"}, "complex": {:hex, :complex, "0.5.0", "af2d2331ff6170b61bb738695e481b27a66780e18763e066ee2cd863d0b1dd92", [:mix], [], "hexpm", "2683bd3c184466cfb94fad74cbfddfaa94b860e27ad4ca1bffe3bff169d91ef1"}, "earmark_parser": {:hex, :earmark_parser, "1.4.37", "2ad73550e27c8946648b06905a57e4d454e4d7229c2dafa72a0348c99d8be5f7", [:mix], [], "hexpm", "6b19783f2802f039806f375610faa22da130b8edc21209d0bff47918bb48360e"}, "ex_doc": {:hex, :ex_doc, "0.30.9", "d691453495c47434c0f2052b08dd91cc32bc4e1a218f86884563448ee2502dd2", [:mix], [{:earmark_parser, "~> 1.4.31", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "d7aaaf21e95dc5cddabf89063327e96867d00013963eadf2c6ad135506a8bc10"}, @@ -9,6 +10,7 @@ "nimble_parsec": {:hex, :nimble_parsec, "1.3.1", "2c54013ecf170e249e9291ed0a62e5832f70a476c61da16f6aac6dca0189f2af", [:mix], [], "hexpm", "2682e3c0b2eb58d90c6375fc0cc30bc7be06f365bf72608804fb9cffa5e1b167"}, "nx": {:hex, :nx, "0.6.2", "f1d137f477b1a6f84f8db638f7a6d5a0f8266caea63c9918aa4583db38ebe1d6", [:mix], [{:complex, "~> 0.5", [hex: :complex, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ac913b68d53f25f6eb39bddcf2d2cd6ea2e9bcb6f25cf86a79e35d0411ba96ad"}, "rustler": {:hex, :rustler, "0.30.0", "cefc49922132b072853fa9b0ca4dc2ffcb452f68fb73b779042b02d545e097fb", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:toml, "~> 0.6", [hex: :toml, repo: "hexpm", optional: false]}], "hexpm", "9ef1abb6a7dda35c47cfc649e6a5a61663af6cf842a55814a554a84607dee389"}, + "rustler_precompiled": {:hex, :rustler_precompiled, "0.7.0", "5d0834fc06dbc76dd1034482f17b1797df0dba9b491cef8bb045fcaca94bcade", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:rustler, "~> 0.23", [hex: :rustler, repo: "hexpm", optional: true]}], "hexpm", "fdf43a6835f4e4de5bfbc4c019bfb8c46d124bd4635fefa3e20d9a2bbbec1512"}, "telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"}, "toml": {:hex, :toml, "0.7.0", "fbcd773caa937d0c7a02c301a1feea25612720ac3fa1ccb8bfd9d30d822911de", [:mix], [], "hexpm", "0690246a2478c1defd100b0c9b89b4ea280a22be9a7b313a8a058a2408a2fa70"}, } diff --git a/native/candlex/.cargo/config.toml b/native/candlex/.cargo/config.toml index 20f03f3..1602afb 100644 --- a/native/candlex/.cargo/config.toml +++ b/native/candlex/.cargo/config.toml @@ -3,3 +3,7 @@ rustflags = [ "-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup", ] + +# Provides a small build size, but takes more time to build. +[profile.release] +lto = true diff --git a/native/candlex/Cargo.toml b/native/candlex/Cargo.toml index af9022e..306760b 100644 --- a/native/candlex/Cargo.toml +++ b/native/candlex/Cargo.toml @@ -13,7 +13,7 @@ crate-type = ["cdylib"] candle-core = { git = "https://github.com/huggingface/candle" } half = "2.3.1" num-traits = "0.2.17" -rustler = "0.30.0" +rustler = { version = "0.30.0", default-features = false, features = ["derive", "nif_version_2_16"] } statrs = "0.16.0" thiserror = "1.0.50"