https://github.com/bake-bake-bake/bakeware Skip to content Sign up * Why GitHub? Features - + Mobile - + Actions - + Codespaces - + Packages - + Security - + Code review - + Project management - + Integrations - + GitHub Sponsors - + Customer stories- * Team * Enterprise * Explore + Explore GitHub - Learn and contribute + Topics - + Collections - + Trending - + Learning Lab - + Open source guides - Connect with others + The ReadME Project - + Events - + Community forum - + GitHub Education - + GitHub Stars program - * Marketplace * Pricing Plans - + Compare plans - + Contact Sales - + Education - [ ] [search-key] * # In this repository All GitHub | Jump to | * No suggested jump to results * # In this repository All GitHub | Jump to | * # In this organization All GitHub | Jump to | * # In this repository All GitHub | Jump to | Sign in Sign up {{ message }} bake-bake-bake / bakeware * Notifications * Star 1k * Fork 32 Compile Elixir applications into single, easily distributed executable binaries View license 1k stars 32 forks Star Notifications * Code * Issues 10 * Pull requests 1 * Actions * Security * Insights More * Code * Issues * Pull requests * Actions * Security * Insights main Switch branches/tags [ ] Branches Tags Could not load branches Nothing to show {{ refName }} default View all branches Could not load tags Nothing to show {{ refName }} default View all tags 3 branches 7 tags Code Clone HTTPS GitHub CLI [https://github.com/b] Use Git or checkout with SVN using the web URL. [gh repo clone bake-b] Work fast with our official CLI. Learn more. * Open with GitHub Desktop * Download ZIP Launching GitHub Desktop If nothing happens, download GitHub Desktop and try again. Go back Launching GitHub Desktop If nothing happens, download GitHub Desktop and try again. Go back Launching Xcode If nothing happens, download Xcode and try again. Go back Launching Visual Studio Code Your codespace will open once ready. There was a problem preparing your codespace, please try again. Latest commit @jjcarstens jjcarstens v0.2.0 release ... 17afc53 Apr 20, 2021 v0.2.0 release 17afc53 Git stats * 135 commits Files Permalink Failed to load latest commit information. Type Name Latest commit message Commit time .circleci CI: run dialyzer Feb 20, 2021 .github/workflows Fix Windows CI script Apr 16, 2021 assets Add more docs Sep 13, 2020 examples Scope bakeware release options to :bakeware Apr 16, 2021 lib Extract executable name helper function Apr 16, 2021 src Add support for Windows Apr 16, 2021 test Extract executable name helper function Apr 16, 2021 .formatter.exs Initial commit Sep 12, 2020 .gitignore Initial commit Sep 12, 2020 CHANGELOG.md v0.2.0 release Apr 19, 2021 Dockerfile instructions for static openssl Mar 25, 2021 LICENSE Apache License v2.0 Oct 23, 2020 Makefile Add support for Windows Apr 16, 2021 README.md Update README with start_command notes Apr 19, 2021 mix.exs v0.2.0 release Apr 19, 2021 mix.lock Bump ex_doc Apr 16, 2021 View code Bakeware Using Mix release Scripting Tips Minimizing executable size Erlang distribution Creating cross-platform binaries Static Compiling OpenSSL into Erlang Distribution Building on Windows Reference material Command-line arguments Environment variables Binary format Cache directory LICENSE README.md Bakeware CircleCI Hex version Hex Docs Total Download License Last updated Compile Elixir applications into single, easily distributed executable binaries The Bakeware oven Bakeware was made over a weekend at SpawnFest 2020 and thanks to the response from the community, we're working on finishing it off. While it's not ready for production, it's definitely ready for experimentation - just expect APIs to change in the near-term. If you'd like to help, please let us know and stay tuned! Bakeware extends Mix releases with the ability to turn Elixir projects into single binaries that can be copied and directly run. No need to install Erlang or untar files. The binaries look and feel like the build-products from other languages. Here's a quick list of features: * Simple - add the bakeware dependency and the Bakeware assembler to your Mix release settings * Supports OSX and Linux (We wrote the code with Windows and the BSDs in mind, so support for those platforms may not be far off) * Zstandard compression for smaller binaries * Optional support for automatic software updates (work in progress) * Command-line argument passing conveniences * Lots of examples This README contains the basics of making your applications work with Bakeware and reference material for when you need to dig into how it works. Since everything was written quickly and the integration is fairly straightforward, we recommend that you take a look at the examples. The examples are bare bones Elixir scripts, OTP applications, Phoenix applications and more with small changes to their mix.exs files and instructions for running that you can try out for yourself. Using Mix release Bakeware supports tieing in executable binary assembly into a Mix release as a step by using the Bakeware.assemble/1 function. This will assemble the necessary components to create a Bakeware executable that can be distributed across machines to run the script/ application without extra environment setup (such as installing Elixir/Erlang, etc) To use, add this to your release as a step after assembly: def release do [ demo: [ steps: [:assemble, &Bakeware.assemble/1] ] ] end Bakeware adds the following options in the release scoped to :bakeware key: * :compression_level - Zstandard compression level (1 to 19) where higher numbers generally result in better compression, but are slower to build * :start_command - The start script command to run when invoked. This defaults to "start", but can be changed to "start_iex", for example, if you want a prompt. See Mix.Release for supported commands. def release do [ demo: [ bakeware: [ compression_level: 1, start_command: "daemon" ] ] ] end Scripting Bakeware supports an API similar to Erlang's escript for implementing a main function. Here's an example module: defmodule MyApp.Main do use Bakeware.Script @impl Bakeware.Script def main(_args) do IO.puts "Hello, World!" 0 end end The return value sets the scripts exit status (0 for success and other values for errors). Other value types are supported. See :erlang.halt/2 for how these work. Next, add this module to your mix.exs's application description. This usually looks something like this: def application do [ extra_applications: [:logger], mod: {Myapp.Main, []} ] end Why does the module get added to :mod? Everything with Bakeware operates on OTP Releases. The macros in Bakeware.Script add the scaffolding to invoke your main/1 function from the release. Tips Minimizing executable size Bakeware binaries appear to have a lower bound of about 12 MB in size. We expect that they can be made smaller out-of-the-box, but here are a few things you can do: 1. Make sure zstd is installed to enable compression during assembly: * MacOS: brew install zstd * Ubuntu: apt-get install zstd 2. Build using MIX_ENV=prod. The default is MIX_ENV=dev, so be sure that the environment variable is set. 3. Run rm -fr _build and then mix release. During development cruft builds up in the release directory. Bakeware can't tell the difference between the important files and the cruft, so executables will slowly grow in size if you don't do a clean build. 4. Inspect your _build/prod/rel/ directory and especially under lib for files or dependencies that you might be including on accident. 5. Make sure that compile-time dependencies are marked as runtime: false in your mix.exs so that they're not included 6. Try raising the compression Zstandard compression level by setting :compression_level in the mix.exs release config Erlang distribution Bakeware uses Mix releases and inherits the default of starting of Erlang distribution. If you're using Bakeware for commandline or other short-lived applications, this unnecessarily starts Erlang distribution servers running and prevents two application instances from running at a time. To disable, run mix release.init to create starter env.sh.eex and env.bat.eex files in the rel directory. Then edit the files to set RELEASE_DISTRIBUTION=none. Creating cross-platform binaries Bakeware binaries include the Erlang runtime but there are still dependencies on the host system. These include the C runtime and other libraries referenced by the Erlang runtime and any NIFs and ports in your application. Luckily, the binary ABIs of many libraries are very stable, but if distributing to a wide audience, it's useful to build on a system with older library versions. Python has a useful pointers in their packaging guides. Static Compiling OpenSSL into Erlang Distribution Sometimes wierd SSL state bugs arise with a release when openssl is not statically compiled in. You're affected by these ssl issues if you see things like an SSL connection being established but after sending the first packet the remote end drops you. Attached is a Dockerfile that can be built with Podman and used to build your baked released. #Edit the versions of libraries in Dockerfile ENV SSL_VERSION=1.1.1j ENV OTP_VERSION=OTP-23.1.4 ENV ELIXIR_VERSION=v1.11.3 #Build erlang with static openssl podman build --tag mybuilder DockerfileFolder/ #Bake your release podman run -it --rm -v .:/root/myproject --entrypoint bash mybuilder -c "cd /root/myproject && ./build.sh" #Build.sh export MIX_ENV=prod rm -rf _build mix deps.get mix release cp _build/prod/rel/bakeware/myproject . Building on Windows Bakeware is tested to work in mingw environment on Windows 8 and 10. In order to setup the environment follow these steps: * Install chocolatey * Install elixir, zstandard, make, and mingw using chocolatey: choco install -y elixir zstandard make mingw * We need to change the default nmake used by elixir_make for Windows to make that we just installed: export MAKE=make * Export the CC variable as well: export CC=gcc * Now everything is set and the final standalone executable should get built withmix release Reference material Command-line arguments In general, command-line arguments passed to Bakeware applications are passed through to Elixir. A few special command-line arguments can be passed to adjust the launchers behavior. Bakeware stops parsing command-line arguments when it encounters a --. Processed command-line arguments are not passed along to Elixir. The following arguments may be passed: * --bw-info - Print out information about the application and exit * --bw-gc - This cleans up all unused entries in the cache (NOT IMPLEMENTED) * --bw-install - Unpack the application to the cache only. Do not run. * --bw-system-install - Install to a system-wide location (NOT IMPLEMENTED) * --bw-command - use the specified Mix.Release command when running the executable Environment variables The Bakeware launcher sets the following environment variables for use in Elixir: Variable name Description BAKEWARE_EXECUTABLE The absolute path to the executable BAKEWARE_ARG1 The first command-line argument BAKEWARE_ARGn The nth command-line argument BAKEWARE_ARGC The number of arguments See the Scripting section of this document for a more user friendly API. Binary format Bakeware application binaries look like this: * Bakeware application launcher * A CPIO archive of an Erlang/OTP release * Trailer The CPIO archive can be compressed. This depends on the contents of the trailer. Trailer format (multi-byte fields are big endian): Offset from Field Type Description end -4 Magic 4 byte Set to "BAKE" string -5 Trailer 8-bit Set to 1 version integer -6 Compression 8-bit 0 = No compression, 1 = integer Zstandard -8 Flags 16-bit Set to 0 (no flags yet) integer -12 Contents 32-bit Offset of CPIO archive offset integer -16 Contents 32-bit Length of CPIO archive length integer -48 SHA1 20 bytes SHA-1 of the CPIO archive Cache directory Bakeware maintains a cache of extracted binaries. This is needed to run the OTP releases and it enables start-time optimizations. The default cache directory location is system-specific: * Windows - "C:/Users//AppData/Local/Bakeware/cache" * MacOS - "~/Library/Caches/Bakeware" * Linux and other Unixes - "~/.cache/bakeware" You can override it by setting the $BAKEWARE_CACHE environment variable. Here's the layout of each cache entry: Path Created Description by $CACHE_DIR/$SHA1/bin CPIO OTP release's bin directory $CACHE_DIR/$SHA1/ CPIO OTP release's ERTS erts-x.y.z $CACHE_DIR/$SHA1/lib CPIO OTP release's lib directory $CACHE_DIR/$SHA1/ CPIO OTP release's releases directory releases $CACHE_DIR/$SHA1/start CPIO Start script. E.g., bin/ my_otp_release start LICENSE All code is licensed under Apache-2.0 with the exception of zstd which is dual licensed BSD/GPL. See it's LICENSE and COPYING files for more details. About Compile Elixir applications into single, easily distributed executable binaries Topics erlang elixir hacktoberfest spawnfest-2020 Resources Readme License View license Releases 7 v0.2.0 Latest Apr 19, 2021 + 6 releases Contributors 8 * @jjcarstens * @fhunleth * @ConnorRigby * @vans163 * @christhekeele * @polvalente * @kritarthh * @kianmeng Languages * C 95.2% * Elixir 3.4% * Other 1.4% * (c) 2021 GitHub, Inc. * Terms * Privacy * Security * Status * Docs * Contact GitHub * Pricing * API * Training * Blog * About You can't perform that action at this time. You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.