EnglishFrançais

6 · Build & tooling

This chapter walks through every script and workflow that builds, tests, and ships Amalgame.

The compiler and its snapshot

Amalgame keeps the self-hosted compiler in tree, plus a portable known-good snapshot:

Cold-start bootstrap

From a clean clone:

gcc -O2 -Iruntime snapshot/amc_lib.c -lgc -lm -o snapshot/amc
./build_amc.sh

Dependencies (Linux):

macOS uses brew install bdw-gc; Windows uses MSYS2 MinGW64 (mingw-w64-x86_64-{gcc,gc}). The same snapshot/amc_lib.c is the cross-platform entry point everywhere.

./build_amc.sh — self-host build

The five-second loop:

Step 1   ./amc src/lexer/*.am src/parser/*.am … src/generator/gen_test.am -o gen_test
         gcc -O2 -Iruntime gen_test.c -o gen_test
Step 2   ./gen_test                 # generates src/amc_lib.c (and inspection bundles)
Step 3   gcc -Iruntime src/amc_lib.c -lgc -lm -o amc

Notes:

The build is hermetic — no environment variables, no global state. Re-running ./build_amc.sh is always safe.

Tests — AM bundles via amc test

Depuis 2026-05-22 la suite de tests vit comme des bundles *_test.am auto-découverts par amc test. Chaque bundle compile ses samples une seule fois et grep-vérifie la stdout capturée pour chaque assertion — ~6× plus rapide que les anciens runners bash (stdlib : 3m34s → 8s). Les runners bash legacy ont été supprimés le 2026-05-24 ; amc test est désormais le seul chemin.

Bundle Cas Couverture
tests/fmt/fmt_test.am 12 Formatter idempotence + semantic preservation
tests/amc_new/amc_new_test.am 38 amc new scaffolder smoke tests
tests/stdlib_bundle/stdlib_test.am 196 IO/String/Collections/Json/Toml/Path/MsgPack/PR + 2 e2e
tests/core_bundle/core_test.am 332 Core lang, namespace, interfaces, enums, lambda, LSP, DAP, LLM tooling
Total 578 + 5 SKIP (HTTP moved to amalgame-net-http)
./amc test ./tests/                 # tout (~42s) — auto-discovery
./amc test ./tests/core_bundle/     # une suite (29s)
./amc test ./tests/stdlib_bundle/   # stdlib uniquement (8s)
./tests/run_all_tests.sh            # wrapper d'une ligne autour de `amc test ./tests/`

Flags

Flag Effet
--filter <pat> N'exécute que les *_test.am dont le chemin contient <pat> (substring, pas une regex)
--ci Sortie terse : drop [PASS]/[SKIP] et les en-têtes par fichier, garde [FAIL] + tally
--list Imprime les chemins découverts (post-filter) et exit 0 — pas de compile, pas de run
--help / -h Imprime ce tableau

amc test prune les répertoires fixtures/ lors du crawl : les fichiers fixture (LSP workspace, test-runner self-test) restent accessibles via un chemin explicite (amc test ./tests/fixtures/<x>/) mais ne sont pas auto-exécutés depuis la racine.

Continuous integration

.github/workflows/ci.yml — runs on every push and PR to main / develop:

Job Runs on What it does
linux ubuntu-latest apt deps · gcc snapshot/amc_lib.c · ./build_amc.sh · tests
macos macos-latest (arm64) brew deps · gcc src/amc_lib.c · smoke compile hello
windows windows-latest (MSYS2) pacman deps · gcc src/amc_lib.c · smoke compile hello

All three platforms validate that the tracked amc_lib.c is portable and produces a working binary.

Releases

.github/workflows/release.yml — runs on every push of a v* tag:

Job What it produces
build-linux amc-X.Y.Z-linux-x86_64.tar.gz + .sha256
build-macos amc-X.Y.Z-macos-arm64.tar.gz + .sha256
build-windows amc-X.Y.Z-windows-x86_64.zip (DLLs bundled) + .sha256
publish aggregates checksums, creates a GitHub Release

The Windows zip bundles the MinGW DLLs the binary actually links against (libgc, libgcc_s_seh, libwinpthread, etc.) — users install the zip and run amc.exe without any external dependency.

Trigger a release:

git tag v0.4.0
git push origin v0.4.0
# CI takes ~10 minutes, the release shows up on GitHub when done.

workflow_dispatch is also enabled for testing the workflow without cutting a real release.

Inno Setup installer (Windows)

install/windows/amalgame.iss produces a .exe installer for Windows users via Inno Setup 6+:

# Drop a portable MinGW64 (e.g. from winlibs.com) into install/windows/gcc-bundle/
iscc install/windows/amalgame.iss
# → Output/amalgame-X.Y.Z-setup.exe

The installer ships amc.exe, runtime/_runtime.h, the docs, and the bundled MinGW64 toolchain so users get a working amc + gcc out of the box.

Homebrew formula

install/homebrew/amalgame.rb — for brew tap distribution. Update the version and SHA256 every release.

Local hygiene

Editor support

editors/vscode/ is a complete VS Code extension (TextMate grammar, language configuration, LSP client, README). Install for development:

ln -s "$(pwd)/editors/vscode" ~/.vscode/extensions/amalgame-0.1.0
# Reload window: Ctrl+Shift+P → Developer: Reload Window

The extension spawns amc lsp on .am files via stdio JSON-RPC. Point it at your local build by setting in your VS Code settings:

"amalgame.serverPath": "/abs/path/to/Amalgame/amc"

The LSP server (since v0.3.4 for diagnostics, v0.3.5 for hover + completion) currently provides:

amc lsp runs in stdio mode by default. Manually drive it for debugging via:

echo -e 'Content-Length: 41\r\n\r\n{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' | ./amc lsp

Debugging .am programs (amc dap, since v0.8.0)

amc dap is a Debug Adapter Protocol server. Since Phase 7 (post-v0.8.46) it defaults to bridge mode: amc spawns gdb --interpreter=mi3 itself and translates DAP↔gdb-MI in-process so AmalgameList* / AmalgameMap* / AmalgameSet* / AmalgameClosure* variables pretty-print with summaries and expandable children, and runtime helper frames (Amalgame_*, _runtime_*, GC_*) are hidden from the call stack. On hosts without gdb (stock macOS, etc.), amc dap falls back transparently to the legacy proxy. amc dap --raw is the explicit opt-out: it execvp()s into the host's DAP-native backend (lldb-dap on macOS, gdb --dap on Linux/MSYS2 with gdb ≥ 14), exactly like v0.8.0 used to. No source map files either way: cgen emits #line N "foo.am" directives so DWARF carries the .am filenames and line numbers natively.

Prerequisites

OS Install one of
Linux lldb-dap from LLVM 18+ (wget https://apt.llvm.org/llvm.sh && sudo ./llvm.sh 18 && sudo apt install -y lldb-18)
macOS Xcode Command Line Tools 14+ (xcode-select --install)
Windows gdb 14+ via MSYS2 (pacman -S mingw-w64-x86_64-gdb) — pending v0.8.1

Workflow — VS Code (recommended)

  1. Scaffold a project with the wiring already in place:
    amc new myapp --vscode      # writes .vscode/launch.json + settings.json
    
  2. Build with DWARF:
    cd myapp && ./build.sh -g   # forwards -g to `amc build`
    
  3. In VS Code: open src/main.am, click in the gutter to set a breakpoint, press F5. The F5 dropdown surfaces two pre-baked configurations — pick "Debug myapp (Linux/macOS)" or "(Windows)" depending on your platform.

The Amalgame VS Code extension (v0.3.0+) registers the amc debug type and exposes a DebugAdapterDescriptorFactory that spawns amc dap with the path from amalgame.dapServerPath (or amalgame.serverPath as fallback). Logs land in the "Amalgame DAP" output channel.

Workflow — lldb CLI (no VS Code needed)

amc build -g hello.am
lldb-18 ./hello
(lldb) breakpoint set --file hello.am --line 5
(lldb) run
(lldb) frame variable     # locals visible by name + Amalgame type
(lldb) next               # step over
(lldb) continue

The DWARF DW_AT_decl_file / DW_AT_decl_line fields point at hello.am, so lldb resolves the .am source line to a real instruction address with no extra setup.

Strategy & limits

The Phase 7 flip (post-v0.8.46) made the in-process bridge ("Approche A") the default. amc spawns gdb --interpreter=mi3 --nx --quiet via fork + pipe + poll(), parses MI3 records, and rewrites traffic in both directions:

The legacy v0.8.0 proxy (Approche C) is still available as amc dap --raw: a transparent execvp to lldb-dap on macOS or gdb --dap on Linux/MSYS2. Useful for users hitting a bridge regression, or for hosts where gdb isn't installed (amc auto-falls-back in that case — no flag needed).