Packages

Embedded Deno JS/TS runtime for Elixir via Rustler NIFs. Bidirectional Elixir<->JS calls and a pooled runtime.

Current section

Files

Jump to
tyrex mix.exs
Raw

mix.exs

defmodule Tyrex.MixProject do
use Mix.Project
@version "0.4.0"
@source_url "https://github.com/nyo16/tyrex"
def project do
[
app: :tyrex,
version: @version,
elixir: "~> 1.18",
start_permanent: Mix.env() == :prod,
aliases: aliases(),
deps: deps(),
description: description(),
package: package(),
docs: docs(),
name: "Tyrex",
source_url: @source_url,
homepage_url: @source_url
]
end
def application do
[
extra_applications: [:logger]
]
end
defp description do
"Embedded Deno JS/TS runtime for Elixir via Rustler NIFs. " <>
"Bidirectional Elixir<->JS calls and a pooled runtime."
end
defp package do
[
files: [
"checksum-Elixir.Tyrex.Native.exs",
"CHANGELOG.md",
"LICENSE",
"lib",
# Required by the documented Alpine/musl and NixOS source-build path:
# it carries the `-crt-static` rustflags those targets need.
"native/tyrex/.cargo/config.toml",
"native/tyrex/Cargo.toml",
"native/tyrex/Cargo.lock",
"native/tyrex/src",
"native/tyrex/extension",
"mix.exs",
"priv/main.js",
"README.md"
],
licenses: ["Apache-2.0"],
links: %{
"GitHub" => @source_url
},
maintainers: ["Niko"]
]
end
defp docs do
[
main: "readme",
extras: [
"README.md",
"CHANGELOG.md",
"LICENSE"
],
source_ref: "v#{@version}",
# `Tyrex.Native` is `@moduledoc false` on purpose — it is the raw NIF
# boundary, not public API — but the README and CHANGELOG legitimately name
# it and its functions when explaining how loading and termination work.
# Without this, ex_doc tries to link those mentions and warns on every
# build. Suppressing the link is right; rewording the prose to avoid
# naming the module would make the explanations worse.
skip_code_autolink_to: [
"Tyrex.Native",
"Tyrex.Native.terminate_runtime/1"
],
groups_for_modules: [
Core: [Tyrex, Tyrex.Error, Tyrex.Runtime],
"Inline JS": [Tyrex.Sigil, Tyrex.Inline],
Pool: [Tyrex.Pool, Tyrex.Pool.Strategy],
Strategies: [
Tyrex.Pool.Strategy.RoundRobin,
Tyrex.Pool.Strategy.Random,
Tyrex.Pool.Strategy.Hash
]
]
]
end
defp deps do
[
{:jason, "~> 1.4"},
{:rustler, "~> 0.38.0", optional: true},
{:rustler_precompiled, "~> 0.7"},
{:ex_doc, "~> 0.34", only: :dev, runtime: false},
{:benchee, "~> 1.3", only: :dev, runtime: false}
]
end
defp aliases do
[
# The checksums are of the archives attached to the GitHub release for the
# current @version, so this can only run once that release exists — hence
# the name. Commit the regenerated file, then publish.
"checksums.after_release": ["rustler_precompiled.download Tyrex.Native --all --print"],
# One function rather than [&guard/1, "hex.publish"]: Mix hands a function
# element the CLI arguments only when it is the *last* element of the alias
# list (`Mix.Task.join_args/3` discards them otherwise), and the guard has
# to see them to tell `hex.publish` from `hex.publish docs`.
"hex.publish": &hex_publish/1
]
end
# The `hex.publish` alias body: guard first, then the real task. The guard is a
# guard, not a generator — it refuses to publish a package whose checksum file
# predates the version being published, and never writes one.
defp hex_publish(args) do
# `mix hex.publish docs` uploads documentation only — no Hex tarball, so no
# checksum file and no NIF archives. Gating it would block a docs fix behind
# a GitHub release that need not exist yet.
if "docs" not in args, do: assert_checksums_current!()
Mix.Task.run("hex.publish", args)
end
# The four targets the release publishes: the `build_nif` matrix in
# .github/workflows/release.yml, and `targets:` in lib/tyrex/native.ex.
@precompiled_targets [
"aarch64-apple-darwin",
"aarch64-unknown-linux-gnu",
"x86_64-apple-darwin",
"x86_64-unknown-linux-gnu"
]
# checksum-Elixir.Tyrex.Native.exs is packaged into the tarball, and
# RustlerPrecompiled resolves the artifact name and raises on a missing entry
# before it makes any network call — so a stale file breaks every precompiled
# target identically, tag or no tag. v0.4.0 was cut with only v0.3.0 entries
# because regenerating the file was prose in a runbook nobody executed.
#
# All four targets are required, not merely one matching line: RustlerPrecompiled
# looks up the single entry for the consumer's own platform, so a file
# regenerated for three of them reads as current here and breaks the fourth.
defp assert_checksums_current! do
file = "checksum-Elixir.Tyrex.Native.exs"
contents = if File.exists?(file), do: File.read!(file), else: ""
missing =
Enum.reject(@precompiled_targets, fn target ->
Regex.match?(
~r/-v#{Regex.escape(@version)}-nif-[\d.]+-#{Regex.escape(target)}\.so\.tar\.gz/,
contents
)
end)
if missing != [] do
Mix.raise("""
#{file} has no v#{@version} entries for:
#{Enum.join(missing, "\n ")}
Cut the v#{@version} GitHub release first (the Precomp NIFs workflow attaches
the four archives), then regenerate and commit the file:
TYREX_BUILD=true mix checksums.after_release
which runs: mix rustler_precompiled.download Tyrex.Native --all --print
TYREX_BUILD=true is not optional: with no checksum entry for v#{@version},
Tyrex.Native cannot load a precompiled artifact and must build from source.
""")
end
end
end