
Hacker News · Mar 2, 2026 · Collected from RSS
Article URL: https://www.dhzdhd.dev/blog/gleam-executable Comments URL: https://news.ycombinator.com/item?id=47220020 Points: 12 # Comments: 0
Table of Contents About Creating a gleam project Methods of creating an executable Erlang target Gleescript (requires system Erlang) Steps Burrito JavaScript target Deno compile Steps Node SEA Steps Bun build —compile Steps Nexe Conclusion About Gleam is a new-ish functional programming language that compiles to Erlang and JavaScript. It features a familiar Rust like syntax while being similar to Elm in complexity and in general is a lot of fun to work with. The problem however is that Gleam does not natively support creating executables. This note/guide explains how to create a Gleam executable in various ways, along with their advantages and caveats. I will be using my WIP project to demonstrate the process of creating an executable throughout the guide. Creating a gleam project Install gleam by following the instructions here Create a new project with gleam new <project_name> Build the project with gleam build --target=erlang|javascript The target is important as it determines the generated output of the build command and hence, the way of packaging the code into an executable. Methods of creating an executable Erlang target Gleescript (requires system Erlang) Gleescript is a tool that allows you to create a single executable from a Gleam project. It uses the Erlang escript stdlib module to create the escript which can then be run on the Erlang VM. The caveat is that it requires the Erlang VM to be installed on the target machine. As quoted by the official docs - The escript can run on any computer that has the Erlang VM installed. Older versions of the virtual machine may not support the newer bytecode contained in the escript. Typically being within a couple major versions of the version used to build the escript is safe. Steps Add gleescript as a dependency using gleam add gleescript Build the project with gleam build --target erlang Create the escript with gleam run -m gleescript Run the executable ./your_project Burrito Burrito is a tool to wrap Elixir applications in a BEAM burrito so as to speak. Unlike gleescript, it does not require the host machine to have the Erlang VM installed. As quoted from the official docs - Builds a self-extracting archive for a Mix project, targeting Windows, MacOS, and Linux, containing: Your compiled BEAM code The required ERTS for your project Compilation artifacts for any elixir-make based NIFs used by the project I have not experimented enough with Burrito to get it working with Gleam but it definitely is worth a try considering it supports Elixir and Erlang projects. Perhaps a project can be converted into an escript and then wrapped with Burrito to create a self-contained executable. JavaScript target Deno compile Deno compile is a command built into Deno that allows you to compile a JavaScript file into a single executable. It bundles a lightweight Deno runtime into the executable, so it can run on any system without requiring Deno to be installed. You still have to bundle the generated Gleam code into a single file using a bundler like Webpack/Parcel/Rollup/Esbuild. Deno used to support bundling applications with deno bundle but it has been deprecated in favor of other bundlers stated before. Steps Build the Gleam project with gleam build --target=javascript Bundle the generated JavaScript files into a single file using a bundler (I am using ESbuild here) esbuild build/dev/javascript/<project_name>/<project_name>.mjs --platform=node --minify-whitespace --minify-syntax --bundle --outfile=bundle.cjs --format=cjs --footer:js=\"main();\" Specify the entrypoint to the Gleam project as the first argument. Next specify the platform as node as my specific project is using Node.js API’s internally (Gleam simplifile package) Minify the output to reduce the size of the executable. Notice that I have minified only the whitespace and syntax and left the identifiers as is which is required for the last step. Specify bundle because we obviously want to bundle the code into a single file. Specify the output file as bundle.cjs and the format as cjs (CommonJS). This was a result of me trying out Node SEA first (the next method) but ESM probably works here too as Deno does not have any explicit declaration that it only supports CommonJS. Specify a footer that calls the main method in the generated file as we are not using the bundled file as a module. Usually the footer is used for adding comments and there might be a better way of doing this that I am not aware of. This however serves the purpose very well. Compile the bundled file into a single executable using deno compile --target=<target_architecture> --output <executable_name> bundle.cjs A lot more flags can be included which are described in the docs Permissions should also be added if the executable needs to access the file system or network. They can be found here Node SEA Node Single Executable Applications (SEA) is an experimental Node v23+ feature that allows the distribution of a Node.js application to a system that does not have Node.js installed. The caveat with this method is that it supports only CommonJS files and you will have to bundle the generated Gleam JavaScript files into a single file using a bundler like Webpack/Parcel/Rollup/Esbuild. Steps Build the Gleam project with gleam build --target=javascript Bundle the generated JavaScript files into a single file using a bundler (I am using ESbuild here) esbuild build/dev/javascript/<project_name>/<project_name>.mjs --platform=node --minify-whitespace --minify-syntax --bundle --outfile=bundle.cjs --format=cjs --footer:js=\"main();\" Specify the entrypoint to the Gleam project as the first argument. Next specify the platform as node as my specific project is using Node.js API’s internally (Gleam simplifile package) Minify the output to reduce the size of the executable. Notice that I have minified only the whitespace and syntax and left the identifiers as is which is required for the last step. Specify bundle because we obviously want to bundle the code into a single file. Specify the output file as bundle.cjs and the format as cjs (CommonJS). This is required for Node SEA. Specify a footer that calls the main method in the generated file as we are not using the bundled file as a module. Usually the footer is used for adding comments and there might be a better way of doing this that I am not aware of. This however serves the purpose very well. The next steps are a lot more complicated that Deno and you can find them here. For my project however, they are - Create a sea-config.json and populate as per instructions in the docs. The main and output are the important fields here. Generate the blob to be injected into the copied Node.js binary using node --experimental-sea-config sea-config.json Create a copy of the Node executable using cp $(command -v node) executable_name Remove the binary signature by following instructions in the docs. Inject the blob into the copied Node.js binary using npx postject executable_name NODE_SEA_BLOB <output>.blob --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 Sign the binary if required Run the binary using ./executable_name Following the steps above resulted in a segfault for me and I am not sure why. I will update this section once I study SEA in more detail. It is clear however that Deno is way simpler to use compared to Node SEA. Bun build —compile Bun build with the compile flag is a Bun feature to bundle a bunch of JS files and then compile them into a single executable. It is similar to Deno compile but does not require a separate bundler. All imported files and packages are bundled into the executable, along with a copy of the Bun runtime. All built-in Bun and Node.js APIs are supported. Steps Build the Gleam project with gleam build --target=javascript bun build --compile --outfile=bundle build/dev/javascript/<project_name>/<project_name>.mjs --footer="main();" That’s it. Bun is incredibly convinient and crazy fast compared to Deno or Node or any of the methods mentioned so far. Nexe Nexe is a command-line utility that compiles your Node.js application into a single executable file. Like Burrito, I have not played around with Nexe enough to get it working with my project but it should be way more straightforward than making Burrito work with Gleam. Conclusion Out of all the tools/libraries that I used, I found Bun to be incredibly fast and also very easy to use. The only problem with Bun and Deno is that due to them bundling their own runtimes, the executables are large, usually exceeding 100MB. I personally do not mind this as I am not using the executables in production but it is something to keep in mind.