Choosing a Racket Packaging Strategy for End-User Delivery
Compare raco make, raco exe, raco distribute, and raco pkg when shipping Racket applications to users who may not have Racket installed.
17 Nov 2025, 03:00 UTC

You have a working Racket program and need to get it onto machines that may not have Racket installed. The packaging choice determines whether users can run the program immediately, how large the download is, and whether you must build separate artifacts for Windows, macOS, and Linux. This guide compares the four supported delivery paths—raco make, raco exe, raco distribute, and raco pkg—so you can match the artifact to your constraints.
Constraints That Drive the Choice
Before selecting a tool, answer three questions:
- Does the target machine have Racket? If not, you must bundle the runtime.
- How many executables or native libraries does the application need? A single launcher is simpler than a multi-process suite.
- Which operating systems must you support? Racket build tools are platform-specific; there is no supported cross-compilation path.
Packaging Options Compared
| Command | Artifact | Racket needed on target | Relative size | Best fit |
|---|---|---|---|---|
raco make | Bytecode .zo | Yes | Small | Fast local builds and CI |
raco exe | Single executable | No | Large | One-binary end-user delivery |
raco distribute | Relocatable directory | No | Large | Apps with several launchers or DLLs |
raco pkg | Package archive | Yes, via raco pkg install | Small | Distribution to Racket users |
Trade-offs in Practice
raco make compiles source to bytecode quickly and produces small files. The trade-off is that users must install a compatible Racket runtime. Bytecode is also version-bound: a .zo compiled under one major Racket release will not load under another.
raco exe embeds the runtime into a single binary, removing the Racket install requirement. That convenience costs disk space—standalone executables commonly reach tens to hundreds of megabytes—and the binary is tied to the operating system and architecture where it was built.
raco distribute also bundles the runtime, but produces a directory rather than one file. This is useful when the application needs multiple launchers, shared libraries, or data files that must sit beside the executable. The directory is relocatable, meaning you can move the whole tree to another path on the same platform.
raco pkg creates an archive that other Racket users install with raco pkg install. It is the smallest artifact and integrates with the Racket ecosystem, but it assumes the end user already has Racket.
Concrete Build and Validation Steps
The following example uses a minimal entry point. Create main.rkt with #lang racket and a call to displayln so you can verify output. All commands below require write access to their output directories and should be run from the directory containing main.rkt unless noted otherwise.
Bytecode for CI or local testing
Run this in your project directory:
raco make main.rkt
Expected check: a file named compiled/main_rkt.zo appears. Load it with the same Racket version using racket main.rkt to confirm it runs. If you later upgrade Racket, recompile rather than shipping stale bytecode.
Standalone executable
Run on the target operating system:
raco exe -o build/myapp main.rkt
Expected check: build/myapp exists and runs when invoked directly. On Unix, inspect it with file build/myapp and ldd build/myapp to confirm the runtime is bundled. On Windows, use dumpbin /dependents build\myapp.exe from a Developer Command Prompt.
Relocatable distribution directory
After building the executable, create a distribution:
raco distribute build/dist build/myapp
Expected check: build/dist contains the launcher and bundled runtime files. Copy the entire directory to a clean container or virtual machine without Racket and run the launcher to confirm it starts.
Package for Racket users
If your audience already has Racket, package the source with raco pkg create and have users install it with raco pkg install. This keeps the artifact small but shifts the runtime burden to the user.
Limitations and Pre-Release Checks
Standalone executables and distributions are platform-specific. Build each target on its own OS or in a matching container; cross-compilation is not supported. Before shipping, compare raco --version on the build and target machines when bytecode is involved.
Compiled bytecode is not encryption. Source can be recovered from .zo files and from executables, so do not rely on these tools to protect secrets.
On macOS, unsigned or ad-hoc binaries may be blocked by Gatekeeper. Test in a clean environment and consider notarization for public distribution.
A practical final check is to run the artifact in a minimal container that lacks Racket. If the program starts and produces the expected output, the packaging decision is validated for that platform.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.