Standalone docker images for legacy Windows/DOS compilers — MSVC 1.0–11.0 (every preserved service pack), Borland C/C++ (Turbo C 2.0, Turbo C++ 3.1, bcc32 5.5), Watcom C (Open Watcom 2.0) and Delphi 1.0. Each image is a self-contained compiler container: the runtime (wine / wibo / DOSBox) and the compiler are baked in, and the entrypoint is the compiler wrapper — you just mount a workdir and pass compiler flags.
This repo is the build source: Dockerfiles, the shared base image,
wrapper scripts and the pinned-source manifest. No compiler binaries
live in this repo — every image downloads its sha256-verified source at
build time from the URL recorded in sources.json (the proprietary trees
live in the community preservation repos the build pulls from; see
Copyright).
These are the same images rebrew uses for
compiler-in-the-loop decompilation, packaged so any tool can use them without
rebrew itself — e.g. a recompile-style compiler-as-a-service
(submit C source + toolchain id, get back the object; a local recompile
service is the reference consumer).
./build.sh # base + all 35 images
./build.sh msvc6 # one image (accepts msvc/6.0-win32 or 6.0-win32)PREFIX env var re-tags the images (PREFIX=archaic ./build.sh →
archaic/msvc:6.0-win32). The base image is built first, then the
toolchain images build in parallel (REBREW_BUILD_JOBS concurrent builds,
default 4; set it to 1 for strictly sequential) — each build downloads its
pinned source tarball, so a full sweep is network-bound and parallelism cuts
wall-clock roughly by the job count. Every image is self-contained; no extra inputs
are needed.
The repo's own glue is checked by three analyzers; make lint runs them
all and must stay green. Both make lint and the behavioral make test
are CI gates (.github/workflows/lint.yml), so findings and contract
breaks block merges. The environment
is pinned twice over: tool versions are exact-pinned in pyproject.toml's
[dependency-groups] (lint) and fully resolved — with sha256 hashes for
every artifact — in the committed uv.lock. CI installs with
uv sync --group lint --locked, so local runs and CI get byte-identical,
hash-verified packages or fail loudly on drift:
- shellcheck over every
.shscript (enable=allvia.shellcheckrc; the two disabled style codes are recorded there with their reasons). The wrappers'# shellcheck source=directives point atbase/wrapper-common.sh, so the shared helpers are analyzed in context. - ruff (
pyproject.toml) checks and formats the Python sources — every defect-oriented rule group that passes clean today is enabled, with any exclusion recorded and justified in the config (100-column hard cap). - mypy in
strictmode, scoped to the whole tree: new Python files are checked by default, dot-directories are skipped automatically.
Behavioral tests (make test) pin two contracts: the wrapper
runner/watchdog behavior via stub runners, and the Quantum .PAK
extractor's numeric contracts (bit-reader word assembly, adaptive-model
frequency invariants, decoder symbol-selection intervals, archive field
bounds) with unit tests over delphi/1.0-win16/pak_extract.py.
After editing Python config locally, uv sync --group lint --locked (or
just uv run make lint) reproduces exactly what CI installs.
Every image's ENTRYPOINT is the compiler wrapper; the container sees your
source through /work (bind-mount your dir, -w /work), flags and source
follow, and the artifact lands back in the mounted dir:
# MSVC 6.0 (wine inside the image)
docker run --rm -v "$PWD":/work -w /work rebrew/msvc:6.0-win32 /c /O2 f.c # → f.obj
# Same image, wibo instead of wine — much faster for plain console tools.
# The wrapper reads REBREW_RUNNER (wine is the default; wibo is the minimal
# decompals PE loader baked into the base image).
docker run --rm -e REBREW_RUNNER=wibo -v "$PWD":/work -w /work rebrew/msvc:6.0-win32 /c /O2 f.c
# MSVC 1.52 / Turbo C 3.1 / Delphi 1.0 (DOSBox inside the image)
docker run --rm -v "$PWD":/work -w /work rebrew/msvc:1.52-win16 /c /O2 f.c
docker run --rm -v "$PWD":/work -w /work rebrew/borland:3.1-win16 -c f.c
docker run --rm -v "$PWD":/work -w /work rebrew/delphi:1.0-win16 hello.dpr
# Watcom (native Linux binary in the image, POSIX-ish flags)
docker run --rm -v "$PWD":/work -w /work rebrew/watcom:2.0-win32 -fo=f.obj -zq f.cThe 32-bit wrappers run the compiler through rebrew_run, which dispatches
on the REBREW_RUNNER env var: wine (default, full Wine — most
compatible) or wibo (the minimal decompals/wibo
PE loader baked into the base image — an order of magnitude faster to start,
good for plain console compilers, but it only implements a subset of Win32;
if a tool misbehaves, fall back to wine). The 16-bit DOSBox toolchains
always use DOSBox and ignore REBREW_RUNNER.
Both runners and the headless DOSBox runs are wrapped in a watchdog so a hung
compile fails loudly instead of blocking forever (the native Watcom entrypoint
is capped by the same knob):
REBREW_RUNNER_TIMEOUT / REBREW_DOSBOX_TIMEOUT cap a run in seconds
(default 600); on expiry the wrapper exits with an explicit error naming
the knob.
The wrapper validates the source (rebrew_pick_source) and forwards every
other argument to the compiler verbatim, so any flag set works — except the
Delphi dcc wrapper, which runs DCC with a fixed configuration baked into
the image and ignores extra arguments. Artifacts are named after the source
(.obj/.o/.exe), FAT-uppercased for the DOSBox runtimes (f.OBJ).
sources.json records, per toolchain: the pinned download URL, sha256,
branch commit and layout. Sources:
- MSVC 1.0–11.0:
archaic-msvc(github.com/archaic-msvc) preservation repos, plusarchaic-toolchains/msvc400and thearchaic-toolchainsservice-pack repos (msvc600_sp{1,2,3,4},msvc900_sp1); VC 6.0 SP3/SP4 from the decomp.memsvc6.3/msvc6.4releases (sha-verified byte-identical to the official SP4 CD). - 16-bit MSVC 1.0/1.5/1.52: reconstructed from the original Microsoft
media — archive.org
en_vc152/en_vc152_202512, WinWorld's VC 1.0 3.5" floppy set (SZDD payloads decompressed). - Turbo C 2.0/3.1, Delphi 1.0: archive.org
turboc20,turboc3.1_202112,delphi10items. - Borland C++ 5.5: archive.org
BorlandC55(official free tools). - Open Watcom 2.0: the project's CI snapshot (moving tag, re-pinned).
Every 32-bit Dockerfile curls its own source and verifies the sha256 inside the build, so a build is reproducible from this repo alone.
The compiler binaries and media are proprietary (Microsoft / Borland / Watcom) and are not in this repository. What's here is our own build glue: Dockerfiles, wrapper scripts, the shared base image and the manifest — all MIT.
The 16-bit toolchains ultimately derive from scans of the original media
(archive.org items and WinWorld floppy sets noted under Sources &
provenance; abandonware — obtaining or using them is at your own
discretion). The builds fetch the reconstructed trees from the
community-run archaic-msvc / archaic-toolchains GitHub repos, pinned by
sha256 in sources.json; see also the provenance notes in the
rebrew TOOLCHAIN docs.