From 5dae96efaa21ce715acaee372407f245f76a851b Mon Sep 17 00:00:00 2001 From: "Tj (bougyman) Vanderpoel" Date: Fri, 14 Aug 2026 14:23:21 -0400 Subject: [PATCH 1/2] feat(build): add mix burrito.dinein task for local binary builds Adds a repo-level Mix task that detects the current host platform, builds the Burrito-wrapped lc release for that single target only (MIX_ENV=prod), then renames the output from lc_ to plain lc in app/burrito_out/ so it's immediately runnable without knowing the target suffix. Co-Authored-By: Claude Sonnet 4.6 --- lib/mix/tasks/burrito.dinein.ex | 121 +++++++++++++++++++++++++ test/mix/tasks/burrito.dinein_test.exs | 16 ++++ 2 files changed, 137 insertions(+) create mode 100644 lib/mix/tasks/burrito.dinein.ex create mode 100644 test/mix/tasks/burrito.dinein_test.exs diff --git a/lib/mix/tasks/burrito.dinein.ex b/lib/mix/tasks/burrito.dinein.ex new file mode 100644 index 0000000..b3c4cd0 --- /dev/null +++ b/lib/mix/tasks/burrito.dinein.ex @@ -0,0 +1,121 @@ +defmodule Mix.Tasks.Burrito.Dinein do + @shortdoc "Builds a local Burrito lc binary for the current host platform" + + @moduledoc """ + #{@shortdoc}. + + mix burrito.dinein [--target TARGET] + + Detects the current host platform, builds `app/`'s Burrito binary for that + single target only (`MIX_ENV=prod BURRITO_TARGET= mix release lc + --overwrite`), then installs it as `app/burrito_out/lc` (dropping the + target suffix) so it's immediately runnable as `./app/burrito_out/lc`. + + Supported targets (auto-detected from the current host): + - `macos_aarch64` — macOS Apple Silicon + - `linux_x86_64` — Linux x86_64 + - `windows_x86_64` — Windows x86_64 + + Pass `--target TARGET` (`-t`) to override detection — useful for explicit + cross-compilation when Zig can produce the target from this host. + """ + + use Mix.Task + + alias RepoTasks.Shell + + @supported_targets ~w[macos_aarch64 linux_x86_64 windows_x86_64] + + @impl Mix.Task + def run(argv) do + {opts, args} = + OptionParser.parse!(argv, strict: [target: :string], aliases: [t: :target]) + + unless args == [] do + Mix.raise("Usage: mix burrito.dinein [--target TARGET]") + end + + target = opts[:target] || detect_target!() + + Mix.shell().info("==> Fetching app/ deps") + Shell.run!("mix", ["deps.get"], cd: "app") + + Mix.shell().info("==> Building Burrito binary for #{target}") + + Shell.run!( + "mix", + ["release", "lc", "--overwrite"], + cd: "app", + env: [{"MIX_ENV", "prod"}, {"BURRITO_TARGET", target}] + ) + + # Burrito names output lc_ (lc_.exe on Windows). + # Rename to plain lc (lc.exe) so it's immediately usable without knowing + # the target suffix. + ext = if target == "windows_x86_64", do: ".exe", else: "" + src = Path.join("app/burrito_out", "lc_#{target}#{ext}") + dst = Path.join("app/burrito_out", "lc#{ext}") + + case File.rename(src, dst) do + :ok -> + Mix.shell().info("==> Built: #{dst}") + + {:error, reason} -> + Mix.raise("Failed to install #{src} as #{dst}: #{:file.format_error(reason)}") + end + + :ok + end + + @doc """ + Returns the Burrito target name matching the current host platform. + + Raises `Mix.Error` with an actionable message on unsupported platforms. + """ + @spec detect_target!() :: String.t() + def detect_target! do + os = detect_os() + cpu = detect_cpu() + + case {os, cpu} do + {:darwin, :aarch64} -> + "macos_aarch64" + + {:linux, :x86_64} -> + "linux_x86_64" + + {:windows, :x86_64} -> + "windows_x86_64" + + {os, cpu} -> + Mix.raise( + "Unsupported platform: #{os}/#{cpu}. " <> + "Supported targets: #{Enum.join(@supported_targets, ", ")}" + ) + end + end + + defp detect_os do + case :os.type() do + {:win32, _} -> :windows + {:unix, :darwin} -> :darwin + {:unix, :linux} -> :linux + end + end + + defp detect_cpu do + arch = + :erlang.system_info(:system_architecture) + |> to_string() + |> String.downcase() + |> String.split("-") + |> List.first() + + case arch do + "x86_64" -> :x86_64 + "aarch64" -> :aarch64 + "arm64" -> :aarch64 + other -> String.to_atom(other) + end + end +end diff --git a/test/mix/tasks/burrito.dinein_test.exs b/test/mix/tasks/burrito.dinein_test.exs new file mode 100644 index 0000000..2fdc847 --- /dev/null +++ b/test/mix/tasks/burrito.dinein_test.exs @@ -0,0 +1,16 @@ +defmodule Mix.Tasks.Burrito.DineinTest do + use ExUnit.Case, async: true + + alias Mix.Tasks.Burrito.Dinein + + test "rejects extra positional arguments" do + assert_raise Mix.Error, "Usage: mix burrito.dinein [--target TARGET]", fn -> + Dinein.run(["extra"]) + end + end + + test "detect_target! returns a known supported target for the current host" do + target = Dinein.detect_target!() + assert target in ~w[macos_aarch64 linux_x86_64 windows_x86_64] + end +end From 26a483c4b01d756d0b52fdcd40351e114a1d60eb Mon Sep 17 00:00:00 2001 From: "Tj (bougyman) Vanderpoel" Date: Fri, 14 Aug 2026 14:32:31 -0400 Subject: [PATCH 2/2] fix(build): harden detect_os/detect_cpu for unsupported platforms Add catch-all to detect_os so unknown Unix variants (FreeBSD, etc.) flow to detect_target!'s actionable Mix.raise instead of crashing with FunctionClauseError. Return raw string from detect_cpu fallback instead of String.to_atom to avoid leaking atoms. Co-Authored-By: Claude Sonnet 4.6 --- lib/mix/tasks/burrito.dinein.ex | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/mix/tasks/burrito.dinein.ex b/lib/mix/tasks/burrito.dinein.ex index b3c4cd0..faed2c6 100644 --- a/lib/mix/tasks/burrito.dinein.ex +++ b/lib/mix/tasks/burrito.dinein.ex @@ -100,6 +100,7 @@ defmodule Mix.Tasks.Burrito.Dinein do {:win32, _} -> :windows {:unix, :darwin} -> :darwin {:unix, :linux} -> :linux + {:unix, other} -> other end end @@ -115,7 +116,7 @@ defmodule Mix.Tasks.Burrito.Dinein do "x86_64" -> :x86_64 "aarch64" -> :aarch64 "arm64" -> :aarch64 - other -> String.to_atom(other) + other -> other end end end