Gleam's lack of native executable support is solved through various creative approaches including Gleescript, Burrito, Deno compile, Node SEA, Bun build, and Nexe, each with distinct trade-offs in complexity and output size.
Gleam represents an intriguing entry in the functional programming landscape, offering Rust-like syntax with Elm-level simplicity while compiling to both Erlang and JavaScript. Yet despite its elegant design, Gleam suffers from a notable limitation: it lacks native support for creating standalone executables. This constraint has spawned a creative ecosystem of workarounds, each with distinct advantages and compromises.
The Gleam Foundation
The journey begins with establishing a Gleam project. Installation follows standard patterns, with the language available through conventional package managers. Creating a new project involves the familiar gleam new <project_name> command, followed by building with gleam build --target=erlang|javascript. This target specification proves crucial, as it determines the compilation output and consequently shapes the executable creation strategy.
Erlang Target Solutions
Gleescript: The Traditional Approach
Gleescript emerges as the most straightforward solution for Erlang targets, leveraging the Erlang escript module to produce single-file executables. The process involves adding Gleescript as a dependency, building the project for the Erlang target, and running the Gleam script to generate the executable.
The elegance of Gleescript lies in its simplicity, but this comes with a significant caveat: the target system must have the Erlang VM installed. The escript documentation provides important context, noting that while these executables can run on any computer with the Erlang VM, compatibility issues may arise with older VM versions. Generally, staying within a couple of major versions of the build environment's Erlang version ensures safe operation.
Burrito: The Self-Contained Alternative
Burrito presents a more sophisticated approach, wrapping Elixir applications in what the documentation describes as a "BEAM burrito." Unlike Gleescript, Burrito eliminates the Erlang VM dependency by bundling the required ERTS (Erlang Runtime System) directly into the executable.
The Burrito approach builds self-extracting archives containing compiled BEAM code, the necessary runtime, and any NIF compilation artifacts. While the author hasn't extensively tested Burrito with Gleam projects, its support for Elixir and Erlang applications suggests potential compatibility. One intriguing possibility involves converting a Gleam project to an escript and then wrapping it with Burrito for true self-containment.
JavaScript Target Solutions
Deno Compile: The Modern Approach
Deno's built-in compilation capability offers a compelling solution for JavaScript targets. The process begins with building the Gleam project for JavaScript, followed by bundling the generated code into a single file using tools like ESBuild.
ESBuild configuration proves critical here. The bundling command must specify Node.js as the platform, particularly when the project utilizes Node.js APIs internally. Minification requires careful consideration—while whitespace and syntax minification reduces executable size, preserving identifier names remains essential for proper execution. The bundling format should be CommonJS, and a footer calling the main function ensures proper initialization without treating the bundled file as a module.
Deno compile then transforms this bundled file into a standalone executable, with additional flags available for target architecture specification and permission management. The process supports file system and network access through appropriate permission flags, making it suitable for applications requiring external resource access.
Node SEA: The Experimental Frontier
Node's Single Executable Applications (SEA) feature represents an experimental approach available in Node v23+. SEA shares similarities with Deno compile but introduces additional complexity. The bundling process mirrors Deno's approach, requiring CommonJS format and careful footer configuration.
However, SEA's implementation proves more intricate. The process involves creating a sea-config.json file, generating a blob for injection into the Node binary, copying the Node executable, removing binary signatures, and using postject for blob injection. Additional steps include optional binary signing and execution.
The author encountered segmentation faults when following these steps, suggesting SEA's experimental nature introduces stability concerns. This complexity positions Deno as a more accessible alternative for most use cases.
Bun Build: The Speed Champion
Bun's compilation feature combines bundling and compilation into a single, remarkably efficient process. Unlike Deno or Node SEA, Bun eliminates the need for separate bundlers, handling both tasks internally.
The command structure proves elegantly simple: bun build --compile --outfile=bundle <entrypoint> --footer="main();". Bun's performance advantages become immediately apparent, with the tool demonstrating exceptional speed compared to alternatives. Furthermore, Bun supports all built-in APIs from both itself and Node.js, providing comprehensive compatibility.
Nexe: The Established Alternative
Nexe represents a mature solution for Node.js application compilation, though the author hasn't extensively tested it with Gleam projects. Its established nature suggests straightforward integration, potentially offering a middle ground between Bun's simplicity and SEA's complexity.
Comparative Analysis and Trade-offs
Each approach presents distinct advantages and limitations. Erlang-based solutions like Gleescript offer simplicity but require runtime dependencies. Burrito eliminates these dependencies but introduces additional complexity in the wrapping process.
JavaScript-based solutions vary significantly in their approach. Deno compile provides a balanced combination of simplicity and functionality, while Node SEA offers deeper integration at the cost of complexity and stability concerns. Bun emerges as the speed champion, though its runtime bundling results in larger executables, typically exceeding 100MB.
The size consideration proves particularly relevant for production deployments. While the author expresses comfort with larger executables for non-production use, this factor may influence decisions for distribution scenarios where file size impacts user experience or bandwidth costs.
Practical Recommendations
For developers prioritizing simplicity and speed, Bun presents an attractive option, particularly for development and testing scenarios where executable size proves less critical. Deno compile offers a solid alternative for those preferring established tooling with good performance characteristics.
Projects requiring true self-containment without runtime dependencies might explore Burrito, though this path demands additional experimentation and potentially conversion steps. Traditional approaches using Gleescript remain viable when Erlang runtime availability can be assumed.
Node SEA, while promising, currently appears best suited for experimental projects or those willing to navigate its complexity and potential stability issues.
The Future of Gleam Deployment
The diversity of solutions reflects both Gleam's growing ecosystem and the broader trend toward single-file executable deployment in functional programming. As these tools mature and potentially converge, Gleam developers can anticipate increasingly streamlined deployment options.
The current landscape demonstrates the language's flexibility and the community's resourcefulness in addressing deployment challenges. Whether through Erlang's traditional escript approach or JavaScript's modern compilation capabilities, Gleam's executable creation ecosystem continues evolving to meet developer needs.
For now, the choice depends on specific project requirements: runtime dependencies, executable size constraints, deployment complexity tolerance, and performance needs. Understanding these trade-offs enables informed decisions that align with project goals and constraints.
The journey from Gleam source to executable, while requiring additional steps compared to natively-supported languages, reveals a rich ecosystem of solutions. Each approach offers unique benefits, ensuring that Gleam developers can find suitable deployment strategies regardless of their specific requirements.

Comments
Please log in or register to join the discussion