TIC-80 is a tiny fantasy computer designed for making, playing, and sharing small games. It provides built-in tools for code, sprites, maps, sound, and music, encouraging rapid prototyping and creative constraints.
Website: https://tic80.com Tools repository: https://git.teletype.hu/tools/tic80-tools
This Makefile provides a simple, reproducible workflow for building TIC-80 Lua projects from multiple source files. It is designed for small indie or experimental projects where the source code is split into logical parts and then merged into a single
.luacartridge.
The workflow is based on four core ideas:
inc/ directory.inc file defines the build order.lua fileThis approach keeps the codebase modular while remaining compatible with TIC-80's single-file cartridge model.
project-root/
├── inc/
│ ├── core.lua
│ ├── player.lua
│ └── world.lua
├── impostor.inc
├── Makefile
└── README.md
inc/ contains all Lua source fragments<project>.inc defines the order in which files are merged<project>.lua is generated automatically.inc FileThe .inc file is a plain text file listing Lua source files in build order:
core.lua
player.lua
world.lua
The order matters. Files listed earlier are concatenated first and must define any globals used later.
make build
<project>.inc (e.g., impostor.inc)inc/<project>.lua (e.g., impostor.lua)make minify
minify.lua) and uses it to process the concatenated Lua file. The original code is backed up as <project>.original.lua.make export VERSION=1.0.0
VERSION variable.build and minify to ensure the code is ready..tic cartridge (e.g., impostor-1.0.0.tic).impostor-1.0.0.html.zip).impostor.tic, impostor.html.zip) for consistency.make export_assets
<project>.lua file.awk to directly parse the generated <project>.lua and saves the extracted data into inc/meta/meta.assets.lua. This allows visual assets to be tracked in version control as source code.make import_assets
.png files in assets/<type>/.tic80 --cli import command to load each asset into the cartridge.make watch
inc/ directory, the .inc file, and the assets/ directory for changes.fswatch to be installed.make lint
luacheck, and remaps line numbers back to the original source files for accurate error reporting.make docs
ldoc to process the compiled <project>.lua file and outputs HTML documentation into the docs/ directory.make install_precommit_hook
.git/hooks/pre-commit that runs make lint.make clean
<project>-*.tic)<project>-*.html.zip)<project>.lua)<project>.original.lua)These targets are designed for automated continuous integration (e.g., Woodpecker CI). Each target reads the version from the .version file created by ci-version.
make ci-versioninc/meta/meta.header.lua.main/master) for development builds (e.g., dev-1.0.0-feature-foo)..version file for subsequent steps.make ci-lintmake lint to statically analyze the Lua source files.make ci-minifymake minify to build the project and minify the output.<project>.lua (minified) and <project>.original.lua (pre-minification backup).make ci-docs<project>.original.lua) using ldoc.<project>-1.0.0-docs.zip).<project>-docs.zip) for convenience.make ci-export.version file..tic and .html.zip artifacts.make ci-artifact.lua, .tic, .html.zip, and -docs.zip artifacts to a remote server using scp.sshpass for SSH authentication.DROPAREA_HOST, DROPAREA_PORT, DROPAREA_USER, DROPAREA_TARGET_PATH).make ci-updatecurl to a predefined update server.UPDATE_SECRET) to authorize the request.| File | Description |
|---|---|
<project>.lua |
Merged and potentially minified Lua source |
<project>.original.lua |
Pre-minification source backup |
<project>.tic |
TIC-80 cartridge |
<project>.html.zip |
Packaged HTML build |
<project>-*-docs.zip |
Versioned documentation archive |
<project>-docs.zip |
Latest documentation archive |
maketic80 available in PATHlua (for minification)luacheck (for linting)ldoc (for documentation)fswatch (only for watch mode)sshpass and curl (for CI/CD targets)This document describes the Woodpecker CI pipeline used to build, export, upload, and publish a TIC-80 game project.
The pipeline logic is almost entirely encapsulated within a Makefile, which is called by each pipeline step. This approach simplifies the CI configuration and keeps the build logic centralized.
The pipeline performs the following steps:
.tic and .html).Each step corresponds to a make ci-* target.
- name: version
image: alpine
commands:
- 'apk add --no-cache make'
- 'make ci-version'
What it does:
make.make ci-version, which reads the version from a Lua source file (inc/meta/meta.header.lua) and saves it to a .version file for subsequent steps to use.- name: lint
image: alpine
commands:
- 'apk add --no-cache make lua5.4 lua5.4-dev luarocks gcc musl-dev'
- 'ln -sf /usr/bin/lua5.4 /usr/bin/lua'
- 'ln -sf /usr/bin/luarocks-5.4 /usr/bin/luarocks'
- 'luarocks install luacheck'
- 'make ci-lint'
What it does:
luacheck.make ci-lint, which statically analyzes all Lua source files for syntax errors, unused variables, and other issues.- name: minify
image: alpine
commands:
- 'apk add --no-cache make lua5.4 curl'
- 'ln -sf /usr/bin/lua5.4 /usr/bin/lua'
- 'make ci-minify'
What it does:
curl.make ci-minify, which builds the project (concatenates source files) and then minifies the output.<project>.lua (minified) and <project>.original.lua (pre-minification backup for documentation generation).- name: docs
image: alpine
commands:
- 'apk add --no-cache make lua5.4 lua5.4-dev luarocks gcc musl-dev zip'
- 'ln -sf /usr/bin/lua5.4 /usr/bin/lua'
- 'ln -sf /usr/bin/luarocks-5.4 /usr/bin/luarocks'
- 'luarocks install ldoc'
- 'make ci-docs'
What it does:
ldoc, and zip.make ci-docs, which generates API documentation from the pre-minification source (<project>.original.lua) using ldoc.impostor-1.0.0-docs.zip) and creates an unversioned copy (impostor-docs.zip).- name: export
image: git.teletype.hu/internal/tic80pro:latest
environment:
XDG_RUNTIME_DIR: /tmp
commands:
- 'make ci-export'
What it does:
make ci-export, which reads the version from the .version file and exports the game. This generates:
.tic cartridge (e.g., impostor-1.0.0.tic)..html.zip web build (e.g., impostor-1.0.0.html.zip).impostor.tic, impostor.html.zip) for consistency.- name: artifact
image: alpine
environment:
DROPAREA_HOST: vps.teletype.hu
DROPAREA_PORT: 2223
DROPAREA_TARGET_PATH: /home/drop
DROPAREA_USER: drop
DROPAREA_SSH_PASSWORD:
from_secret: droparea_ssh_password
commands:
- 'apk add --no-cache make openssh-client sshpass'
- 'make ci-artifact'
What it does:
make and SSH tooling.make ci-artifact, which uploads the generated .lua, .tic, .html.zip, and -docs.zip files to a remote server using scp.Makefile target reads the necessary environment variables.- name: update
image: alpine
environment:
UPDATE_SERVER: https://games.vps.teletype.hu
UPDATE_SECRET:
from_secret: update_secret_key
commands:
- 'apk add --no-cache make curl'
- 'make ci-update'
What it does:
make and curl.make ci-update, which sends an HTTP curl request to an update server.After a successful run:
.lua, .tic, .html.zip, -docs.zip) are uploaded to the server.This pipeline enables fully automated TIC-80 releases where the entire build and release logic is managed by the project's Makefile.
https://git.teletype.hu/tools/tic80-tools/src/branch/master/example-woodpecker.yaml
This document provides a guide for creating a Docker-based build environment specifically for compiling the TIC-80 Pro version to be used in automated pipelines.
TIC-80 Pro is a commercial product that offers additional features and supports the ongoing development of the platform. The Pro version is available for purchase on itch.io.
While the TIC-80 source code is open, building the Pro version is intended for users who have purchased a license. If you have bought TIC-80 Pro, you are encouraged to use this Dockerfile to build your own Pro binary from source within a clean and isolated environment, ensuring consistency across your development and CI/CD workflows.
The provided Dockerfile automates the setup of the compilation environment and the build process itself. Below is a step-by-step breakdown of how it works:
FROM ubuntu:24.04
Sets the base image to Ubuntu 24.04 (Noble Numbat), providing a stable and modern Linux foundation for the build.
RUN apt-get update && apt-get install -y ...
Updates the package lists and installs all necessary development tools and libraries:
build-essential and cmake: Core tools for compiling C++ projects.git: Required to clone the source code repository.libsdl2-dev, libpipewire-0.3-dev, libwayland-dev, etc.: Libraries for graphics, audio, and system integration.ruby-dev, lua5.4, libcurl4-openssl-dev: Dependencies for scripting languages and networking features supported by TIC-80.rm -rf /var/lib/apt/lists/* to keep the image size small by removing temporary cache files.RUN git clone --recursive https://github.com/nesbox/TIC-80 /opt/TIC-80
Downloads the TIC-80 source code from GitHub into the /opt/TIC-80 directory, including all necessary submodules.
cd /opt/TIC-80/build && cmake ...
Enters the build directory and configures the project using CMake with specific flags:
-DBUILD_PRO=On: This is the crucial flag that enables the Pro features during compilation.-DBUILD_SDLGPU=On, -DBUILD_WITH_ALL=On: Enables all optional features and GPU support.-DBUILD_STATIC=On: Ensures that the resulting binary is statically linked, making it more portable across different Linux environments.cmake --build . --parallel
Starts the actual compilation process, utilizing multiple CPU cores to speed up the build.
ENV PATH="/opt/TIC-80/build/bin:${PATH}"
Adds the directory containing the newly built TIC-80 binary to the system's PATH, allowing you to run tic80 from anywhere inside the container.
WORKDIR /workspace
Sets the default working directory to /workspace, which is the intended location for mounting your project files.
CMD ["/bin/bash"]
Defines the default command to start a bash shell when the container is run, providing an interactive environment if needed.