Chapter 12: Shipping a cross-platform desktop game
This chapter:
- Build an optimised release binary.
- Understand how raylib gets linked in, and cross-compile for the other desktops.
- Write the everyday
run.sh/build.sh, and know what shipping actually involves.
Where we left off: a complete, deterministic, sounding game, run so far only with odin run.
12.1 Debug and release
All book long you've used one command:
odin run .
It compiles a throwaway binary and runs it: perfect for the edit-run-play loop. To produce a binary you keep, optimised for speed:
odin build . -out:skoll -o:speed
-out:skollnames the executable (skoll.exeon Windows).-o:speedturns on optimisation. During development the default (-o:none, or-o:minimal) builds faster; for a release you want-o:speed. There's also-o:sizeif a small binary matters more than raw speed; for a game,-o:speed.
That single file is the whole game. Run it directly: ./skoll.
12.2 How raylib gets in
When you import rl "vendor:raylib", the compiler links against the prebuilt raylib static library that ships in your Odin distribution under vendor/raylib: a .a on macOS/Linux, a .lib on Windows, one per platform. "Static" means raylib's code is copied into your executable at link time.
The upshot: your release binary has no runtime dependency on a raylib shared object. You ship one file; the person running it needs nothing raylib-related installed.
Odin note: the system libraries raylib still uses. raylib itself calls the operating system's own graphics, windowing and audio (OpenGL/Metal, the window server, Core Audio / ALSA / WASAPI). Those are part of every desktop OS already, so there's still nothing for your player to install, but that's why the game needs a real desktop and can't run on a headless box with no display.
12.3 Cross-compiling
Odin can target another OS/architecture from your machine with -target::
odin build . -out:skoll.exe -o:speed -target:windows_amd64
odin build . -out:skoll -o:speed -target:darwin_arm64
odin build . -out:skoll -o:speed -target:linux_amd64
Cross-compilation depends on the right per-target raylib library and system linker being available; where it isn't set up, the pragmatic path is to build on each OS directly, or to let a CI service build all three from the one source tree. Either way the source never changes: that's the promise of "one source, three platforms", and it's the headline difference from the sibling WebAssembly book (whose one target is the browser).
12.4 The scripts
Two small scripts capture the two commands. run.sh, the everyday loop:
#!/usr/bin/env sh
# run.sh: compile and launch in one step.
set -e
odin run . -out:skoll
build.sh, an optimised release for the host, with a soft size check:
#!/usr/bin/env sh
# build.sh, a release build: one optimised, self-contained native binary.
set -e
OUT=skoll
[ "$(uname)" = "Windows_NT" ] && OUT=skoll.exe
odin build . -out:"$OUT" -o:speed
SIZE=$(wc -c < "$OUT")
echo "Built $OUT (${SIZE} bytes)"
[ "$SIZE" -gt 8000000 ] && echo "note: binary is over 8 MB" || true
On Windows, the same two odin commands work from PowerShell or a .bat; only the shell wrapper differs. Treat these as a starting point and adapt them.
12.5 Shipping it
To hand Sköll to someone: build the release binary for their platform and give them the file. That's genuinely it: zip it if you like, or wrap it in the minimal per-OS bundle a store expects (an .app folder on macOS, an installer on Windows). What you'd add next, without breaking the zero-assets spirit of the core game:
- A window icon (raylib can set one at runtime from an in-memory image).
- A version string, and a
--versionflag. - The correct per-user save path from Chapter 11.
12.6 Where to go next
You've built a complete desktop game and, more importantly, learned a real slice of Odin doing it: types and array programming, structs and enums and single-source tables, pointers and for &x, defer, context and calling conventions, C interop, allocation-free hot loops, seeded determinism, and the whole build-and-ship story.
The features Sköll deliberately skipped are exactly raylib's strengths, and you're now ready for them (Appendix C sketches each):
- Textures and sprites, tilemaps: the moment you want real art.
- Real fonts with
LoadFontEx, for full Unicode text. raygui: raylib's immediate-mode UI toolkit, bundled too.- Shaders and 3D: raylib does both.
Beyond raylib:
- The Odin community is welcoming and active: the Discord, the GitHub (https://github.com/odin-lang/Odin), and the showcase.
- The sibling book Yo Odin (https://nofuss.co.za/yo_odin/) tells the same story on the web: Odin compiled to WebAssembly, a game built down to the browser boundary with a hand-written renderer. If you want the web target, it's the natural next read.
- This book didn't have room for the whole language, properly and thoroughly. For that, Karl Zylinski's *Understanding the Odin Programming Language* is the book to own.
Checkpoint
Sköll is a finished, optimised, self-contained, deterministic, sounding, persistent native binary that you can build for Windows, macOS and Linux from one unchanged source tree and hand to a friend with nothing else to install. You set out not knowing Odin; you're leaving having shipped a game in it.
Exercises
- Run
./build.shand note the binary size. Rebuild with-o:sizeand compare. - Cross-compile for another platform you have access to, and run it there.
- Set a window icon at runtime (see Appendix C): the one asset-adjacent touch that's still generated, not loaded.
- Add a
--versionflag by readingos.argsat the top ofmain.
Further reading
- Odin build flags (
-o,-target,-out):odin build --help, and https://odin-lang.org/docs/install/. - raylib distribution notes: https://github.com/raysan5/raylib/wiki
- raylib home and examples: https://www.raylib.com/ · https://www.raylib.com/examples.html
- Understanding the Odin Programming Language: https://odinbook.com/