Mascota Batamanta

Empaqueta tus aplicaciones Elixir como ejecutables 100% autocontenidos. No requiere Erlang/Elixir en la máquina destino.


Características

  • Binarios autocontenidos: Un único archivo con tu app + ERTS incluido
  • Compilación cruzada: Construye para Linux, macOS y Windows desde cualquier plataforma
  • Compresión Zstandard: Óptimo equilibrio entre tamaño y velocidad
  • Múltiples modos de ejecución: CLI, TUI y Daemon
  • Caché inteligente: Las descargas de ERTS se almacenan localmente

Requisitos

  • Erlang/OTP 25+
  • Elixir 1.15+
  • Rust (cargo)
  • Zstandard (zstd)

Dependencias del Banner (Opcional)

Cuando show_banner: true (por defecto), el proceso de construcción muestra un banner con imagen en la terminal. Para habilitar el soporte completo de imágenes en todos los terminales, instala estas dependencias:

macOS

# Para soporte Sixel (Alacritty, Ghostty, otros terminales)
brew install libsixel

# Opcional: para fallback a ASCII art
# img2txt viene incluido en libsixel

Linux

# Ubuntu/Debian
sudo apt install libsixel-tools

# Arch Linux
sudo pacman -S libsixel

# Fedora
sudo dnf install libsixel

Compatibilidad de Terminales

TerminalProtocoloRequiere
iTerm2Inline ImagesIncorporado
GhosttyProtocolo KittyIncorporado
WezTermProtocolo KittyIncorporado
AlacrittyProtocolo KittyIncorporado
KittyProtocolo KittyIncorporado
VS CodeSixellibsixel
footSixellibsixel
Otros terminalesFallback ASCIINinguno

Si no se detecta soporte de imágenes, el banner usa el modo solo texto.


Uso Rápido

1. Añadir Dependencia

# mix.exs
def deps do
  [{:batamanta, "~> 1.0", runtime: false}]
end

2. Configurar

def project do
  [
    app: :mi_app,
    version: "0.1.0",
    batamanta: [
      erts_target: :auto,        # Auto-detectar plataforma (RECOMENDADO)
      execution_mode: :cli,      # :cli | :tui | :daemon
      compression: 3,           # 1-19 (nivel zstd)
      binary_name: "mi_app",     # Opcional: nombre personalizado
      show_banner: true          # Opcional: mostrar banner de construcción
    ]
  ]
end

Opciones de Configuración

OpciónTipoDefaultDescripción
erts_targetatom:autoPlataforma objetivo (ver abajo)
execution_modeatom:cli:cli, :tui, o :daemon
compressioninteger3Nivel de compresión zstd (1-19)
binary_namestringnombre de appNombre personalizado del binario
show_bannerbooleantrueMostrar banner de construcción
force_osstringnilForzar SO: "linux", "macos", "windows"
force_archstringnilForzar arquitectura: "x86_64", "aarch64"
force_libcstringnilForzar libc: "gnu", "musl" (solo Linux)

Nota para Linux: El objetivo (glibc vs musl) se detecta automáticamente según tu distribución:

  • Debian, Ubuntu, Arch, Fedora, CachyOS → usa linux-gnu
  • Alpine Linux → usa linux-musl

3. Construir

mix batamanta

Esto genera: mi_app-0.1.0-x86_64-linux


Opciones CLI

Sobrescribir configuración desde línea de comandos:

# Usar auto-detección (default)
mix batamanta

# Forzar objetivo ERTS
mix batamanta --erts-target alpine_3_19_x86_64

# Forzar componentes individuales
mix batamanta --force-os linux --force-arch aarch64 --force-libc musl

# Ajustar nivel de compresión
mix batamanta --compression 9

# Combinar opciones
mix batamanta --erts-target ubuntu_22_04_arm64 --compression 5

Flags CLI Disponibles

FlagDescripción
--erts-targetSobrescribir objetivo ERTS
--force-osForzar SO: linux, macos, windows
--force-archForzar arquitectura: x86_64, aarch64
--force-libcForzar libc: gnu, musl (solo Linux)
--compressionNivel de compresión zstd (1-19)

Modos de Ejecución

ModoDescripciónPlataforma
:cliCLI estándar con stdin/stdout/stderr heredadosTodos
:tuiUI de texto con modo terminal raw, navegación con teclas de flechasUnix only
:daemonEjecuta en segundo plano, sin E/S de terminalUnix only

Para Aplicaciones CLI

Al no haber wrapper de shell, usa :init de Erlang para leer argumentos:

defmodule MiApp do
  use Application

  @impl true
  def start(_type, _args) do
    args = :init.get_plain_arguments()
           |> Enum.map(&to_string/1)
           |> Enum.reject(&(&1 == "--"))
    
    case args do
      ["hola", nombre] -> IO.puts("Hola, #{nombre}!")
      _ -> IO.puts("Uso: mi_app hola <nombre>")
    end
    
    System.halt(0)
  end
end

¡No olvides System.halt/1 cuando tu CLI termine!


Objetivos ERTS Soportados

Batamanta usa un sistema unificado de objetivo ERTS para especificar la plataforma.

Targets Soportados

Target AtomSOArqLibcCaso de Uso
:auto---Auto-detectar host (default)
:ubuntu_22_04_x86_64Linuxx86_64glibcDebian, Ubuntu, Arch, CachyOS
:ubuntu_22_04_arm64Linuxaarch64glibcServidores ARM, Raspberry Pi 4
:alpine_3_19_x86_64Linuxx86_64muslAlpine Linux, contenedores
:alpine_3_19_arm64Linuxaarch64muslAlpine en ARM
:macos_12_x86_64macOSx86_64-Mac Intel
:macos_12_arm64macOSaarch64-Apple Silicon (M1/M2/M3)
:windows_x86_64Windowsx86_64msvcPróximamente

Override Manual

Fuerza un objetivo específico independientemente del host:

batamanta: [
  erts_target: :alpine_3_19_x86_64,  # Forzar musl
  execution_mode: :cli
]

O usa overrides individuales:

batamanta: [
  force_os: "linux",
  force_arch: "x86_64",
  force_libc: "musl"
]

Compilación cruzada desde macOS: Instala los targets de Rust:

rustup target add x86_64-unknown-linux-gnu
rustup target add aarch64-unknown-linux-gnu
rustup target add x86_64-unknown-linux-musl
rustup target add aarch64-unknown-linux-musl

Arquitectura

  1. Release: mix release compila tu código
  2. Fetch: Descarga el ERTS correspondiente a la plataforma objetivo
  3. Package: Crea el tarball comprimido (release + ERTS)
  4. Compile: El dispenser de Rust embeber el payload
  5. Run: El dispenser extrae el payload y lanza la VM de Erlang

Repositorio de ERTS

Batamanta usa un repositorio separado para binarios ERTS precompilados:

Batamanta ERTS Repository

Este repositorio aloja binarios ERTS precompilados para:

  • macOS: aarch64 (Apple Silicon)
  • Linux (glibc): x86_64 & aarch64
  • Linux (musl): x86_64 & aarch64

Los binarios están compilados desde las fuentes oficiales de Erlang/OTP y están sujetos a la Licencia Apache 2.0 (consulta el repositorio para más detalles).


Licencia

MIT