···11+# Building Ant
22+33+Depending on what platform or features you need, the build process may
44+differ. After you've built a binary, running the
55+test suite to confirm that the binary works as intended is a good next step.
66+77+## Table of contents
88+99+- [Supported platforms](#supported-platforms)
1010+ - [Platform list](#platform-list)
1111+ - [Supported toolchains](#supported-toolchains)
1212+ - [Official binary platforms and toolchains](#official-binary-platforms-and-toolchains)
1313+- [Building Ant on supported platforms](#building-ant-on-supported-platforms)
1414+ - [Prerequisites](#prerequisites)
1515+ - [Unix and macOS](#unix-and-macos)
1616+ - [Unix prerequisites](#unix-prerequisites)
1717+ - [macOS prerequisites](#macos-prerequisites)
1818+ - [Building Ant](#building-ant-1)
1919+ - [Installing Ant](#installing-ant)
2020+ - [Running tests](#running-tests)
2121+ - [Building a debug build](#building-a-debug-build)
2222+ - [Building an ASan build](#building-an-asan-build)
2323+ - [Speeding up frequent rebuilds when developing](#speeding-up-frequent-rebuilds-when-developing)
2424+ - [Troubleshooting Unix and macOS builds](#troubleshooting-unix-and-macos-builds)
2525+ - [Windows](#windows)
2626+ - [Windows prerequisites](#windows-prerequisites)
2727+ - [Building Ant](#building-ant-2)
2828+- [Meson build options](#meson-build-options)
2929+- [TLS library selection](#tls-library-selection)
3030+3131+## Supported platforms
3232+3333+### Platform list
3434+3535+Ant builds and runs on the following platforms. Official CI builds are
3636+produced for each platform listed below.
3737+3838+| Operating System | Architectures | Variant | Static | Notes |
3939+| ---------------- | ------------- | ---------- | ------ | ---------------------------- |
4040+| GNU/Linux | x64 | glibc | No | Ubuntu 22.04 (CI) |
4141+| GNU/Linux | aarch64 | glibc | No | Ubuntu 22.04 (CI) |
4242+| GNU/Linux | x64 | musl | Yes | Alpine Edge (CI) |
4343+| GNU/Linux | aarch64 | musl | Yes | Alpine Edge (CI) |
4444+| macOS | x64 | openssl | No | macOS 15 (CI) |
4545+| macOS | aarch64 | openssl | No | macOS 15 (CI) |
4646+| macOS | x64 | mbedtls | No | macOS 15 (CI) |
4747+| macOS | aarch64 | mbedtls | No | macOS 15 (CI) |
4848+| Windows | x64 | mingw/msys | No | MSYS2 MINGW64 toolchain (CI) |
4949+5050+### Supported toolchains
5151+5252+Ant is built with the GNU C23 standard (`-std=gnu23`). A compiler with
5353+C23 support is required.
5454+5555+| Operating System | Compiler Versions |
5656+| ---------------- | ------------------------------------- |
5757+| Linux | GCC >= 14 or Clang >= 18 |
5858+| macOS | Xcode CLT (Apple Clang) or LLVM >= 18 |
5959+| Windows | MinGW-w64 GCC via MSYS2 (MINGW64) |
6060+6161+### Official binary platforms and toolchains
6262+6363+CI binaries are produced using:
6464+6565+| Binary package | Platform and Toolchain |
6666+| -------------------------- | -------------------------------------------- |
6767+| ant-linux-x64 | Ubuntu 22.04 (glibc), LLVM/Clang |
6868+| ant-linux-aarch64 | Ubuntu 22.04 (glibc), LLVM/Clang |
6969+| ant-linux-x64-musl | Alpine Edge (musl), statically linked, Clang |
7070+| ant-linux-aarch64-musl | Alpine Edge (musl), statically linked, Clang |
7171+| ant-darwin-x64 | macOS 15 Intel, LLVM/Clang |
7272+| ant-darwin-aarch64 | macOS 15 ARM, LLVM/Clang |
7373+| ant-darwin-x64-mbedtls | macOS 15 Intel, LLVM/Clang, mbedTLS |
7474+| ant-darwin-aarch64-mbedtls | macOS 15 ARM, LLVM/Clang, mbedTLS |
7575+| ant-windows-x64 | MSYS2 MINGW64 toolchain |
7676+7777+## Building Ant on supported platforms
7878+7979+### Prerequisites
8080+8181+The following tools are required to build Ant regardless of platform:
8282+8383+- **C compiler** with C23 support (GCC >= 14 or Clang >= 18)
8484+- **[Meson](https://mesonbuild.com/)** build system (and Ninja backend)
8585+- **[CMake](https://cmake.org/)** (for the tlsuv subproject)
8686+- **pkg-config**
8787+- **Node.js** >= 22 (used to generate the JS snapshot at build time)
8888+- **[Rust](https://rustup.rs/)** toolchain (stable) with `cargo` (builds the OXC type-strip library)
8989+- **[Zig](https://ziglang.org/)** >= 0.15 (builds the package manager component)
9090+- **Git**
9191+9292+System libraries required:
9393+9494+- **OpenSSL** (default) or **mbedTLS** (alternative TLS backend)
9595+- **libsodium**
9696+- **libuuid** (Linux/macOS)
9797+- **llhttp** (if not building from source via cmake)
9898+9999+The remaining dependencies are vendored as Meson subprojects under `vendor/`
100100+and are fetched automatically:
101101+102102+- libuv 1.51.0
103103+- yyjson 0.12.0
104104+- zlib-ng 2.3.2
105105+- nghttp2
106106+- pcre2
107107+- libffi
108108+- lmdb (OpenLDAP LMDB 0.9.33)
109109+- minicoro
110110+- argtable3
111111+- uthash
112112+- uuidv7
113113+- tlsuv (cmake subproject)
114114+115115+### Unix and macOS
116116+117117+#### Unix prerequisites
118118+119119+Installation via package manager:
120120+121121+- Ubuntu/Debian:
122122+123123+ ```bash
124124+ sudo apt-get install python3 python3-pip gcc-14 g++-14 ninja-build cmake \
125125+ pkg-config uuid-dev libssl-dev libsodium-dev nodejs npm
126126+ pip3 install meson
127127+ ```
128128+129129+- Fedora:
130130+131131+ ```bash
132132+ sudo dnf install python3 gcc gcc-c++ ninja-build cmake pkgconf \
133133+ libuuid-devel openssl-devel libsodium-devel nodejs npm
134134+ pip3 install meson
135135+ ```
136136+137137+- Alpine (musl):
138138+ ```sh
139139+ apk add clang lld llvm meson ninja cmake pkgconf nodejs npm \
140140+ musl-dev openssl-dev openssl-libs-static libsodium-dev libsodium-static \
141141+ util-linux-dev util-linux-static linux-headers libunwind-dev libunwind-static
142142+ ```
143143+144144+You will also need Rust and Zig installed. The recommended approach:
145145+146146+```bash
147147+# Rust (via rustup)
148148+curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
149149+150150+# Zig (download from https://ziglang.org/download/)
151151+# Or via package manager if available
152152+```
153153+154154+#### macOS prerequisites
155155+156156+- Xcode Command Line Tools (provides Apple Clang):
157157+158158+ ```bash
159159+ xcode-select --install
160160+ ```
161161+162162+- Install remaining tools via [Homebrew](https://brew.sh):
163163+164164+ ```bash
165165+ brew install meson ninja llvm openssl@3 libsodium node
166166+ ```
167167+168168+- Rust and Zig:
169169+170170+ ```bash
171171+ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
172172+ brew install zig
173173+ ```
174174+175175+#### Building Ant
176176+177177+To build Ant:
178178+179179+```bash
180180+meson subprojects download
181181+meson setup build
182182+meson compile -C build
183183+```
184184+185185+Alternatively, if you have [maid](https://github.com/exact-labs/maid) installed, <br>
186186+you can use the task runner:
187187+188188+```bash
189189+maid setup # downloads subprojects + configures with ccache and lld
190190+maid build # compiles
191191+maid run <file> # builds and runs a JS file
192192+```
193193+194194+To verify the build:
195195+196196+```bash
197197+./build/ant --version
198198+./build/ant -e "console.log('Hello from Ant ' + Ant.version)"
199199+```
200200+201201+#### Installing Ant
202202+203203+You can install the built binary using:
204204+205205+```bash
206206+maid install
207207+```
208208+209209+This copies the binary to the directory of an existing `ant` installation, or
210210+falls back to `~/.ant/bin/`. It also creates an `antx` symlink.
211211+212212+Alternatively, copy the binary manually:
213213+214214+```bash
215215+cp ./build/ant /usr/local/bin/ant
216216+```
217217+218218+#### Running tests
219219+220220+To run a single test:
221221+222222+```bash
223223+./build/ant tests/test_async.cjs
224224+```
225225+226226+To run the spec suite:
227227+228228+```bash
229229+./build/ant examples/spec/run.js
230230+```
231231+232232+#### Building a debug build
233233+234234+A debug build disables optimizations and LTO, and preserves debug symbols:
235235+236236+```bash
237237+meson subprojects download
238238+CC="ccache $(which clang)" \
239239+ meson setup build --wipe --buildtype=debug \
240240+ -Doptimization=0 -Db_lto=false -Dstrip=false -Db_lundef=false -Dunity=off
241241+meson compile -C build
242242+```
243243+244244+Or with maid:
245245+246246+```bash
247247+maid debug
248248+maid build
249249+```
250250+251251+When using the debug build, core dumps will be generated in case of crashes.
252252+Use `lldb` or `gdb` with the debug binary to inspect them:
253253+254254+```bash
255255+lldb ./build/ant core.ant
256256+(lldb) bt
257257+```
258258+259259+#### Building an ASan build
260260+261261+[ASan](https://github.com/google/sanitizers) can help detect memory bugs:
262262+263263+```bash
264264+meson subprojects download
265265+CC="ccache $(which clang)" \
266266+ meson setup build --wipe \
267267+ -Db_sanitize=address -Doptimization=0 -Db_lto=false -Dstrip=false -Db_lundef=false
268268+meson compile -C build
269269+```
270270+271271+Or with maid:
272272+273273+```bash
274274+maid asan
275275+maid build
276276+```
277277+278278+Then run tests against the ASan build:
279279+280280+```bash
281281+./build/ant tests/test_gc.js
282282+```
283283+284284+#### Speeding up frequent rebuilds when developing
285285+286286+If you plan to frequently rebuild Ant, installing `ccache` can greatly
287287+reduce build times. The `maid setup` task configures ccache automatically.
288288+289289+On GNU/Linux:
290290+291291+```bash
292292+sudo apt install ccache
293293+export CC="ccache gcc" # add to your .profile
294294+```
295295+296296+On macOS:
297297+298298+```bash
299299+brew install ccache
300300+export CC="ccache cc" # add to ~/.zshrc
301301+```
302302+303303+Using `lld` as the linker also speeds up link times:
304304+305305+```bash
306306+export CC_LD="$(which ld64.lld)" # macOS with brew llvm
307307+# or
308308+export CC_LD="$(which lld)" # Linux
309309+```
310310+311311+Note: LTO is enabled by default with 8 threads (`b_lto=true`,
312312+`b_lto_threads=8`). Disable it with `-Db_lto=false` for faster iteration
313313+during development.
314314+315315+#### Troubleshooting Unix and macOS builds
316316+317317+Stale builds can sometimes result in errors. Clean the build directory and
318318+reconfigure:
319319+320320+```bash
321321+rm -rf build
322322+meson setup build
323323+meson compile -C build
324324+```
325325+326326+If you encounter "file not found" errors for vendored dependencies:
327327+328328+```bash
329329+meson subprojects download
330330+```
331331+332332+If the build runs out of memory, reduce parallelism:
333333+334334+```bash
335335+meson compile -C build -j2
336336+```
337337+338338+### Windows
339339+340340+#### Windows prerequisites
341341+342342+Ant on Windows is built using the MSYS2 MINGW64 toolchain. Native MSVC
343343+builds are not currently supported.
344344+345345+1. Install [MSYS2](https://www.msys2.org/)
346346+2. Open the **MINGW64** shell and install dependencies:
347347+ ```bash
348348+ pacman -S mingw-w64-x86_64-toolchain mingw-w64-x86_64-meson \
349349+ mingw-w64-x86_64-ninja mingw-w64-x86_64-cmake \
350350+ mingw-w64-x86_64-openssl mingw-w64-x86_64-libsodium \
351351+ mingw-w64-x86_64-lld mingw-w64-x86_64-nodejs git
352352+ ```
353353+3. Install Rust via [rustup](https://rustup.rs/) (select the
354354+ `x86_64-pc-windows-gnu` target)
355355+4. Install [Zig](https://ziglang.org/download/)
356356+357357+#### Building Ant
358358+359359+From the MSYS2 MINGW64 shell:
360360+361361+```bash
362362+git clone https://github.com/theMackabu/ant.git
363363+cd ant
364364+meson subprojects download
365365+meson setup build -Dc_std=gnu2x
366366+meson compile -C build
367367+```
368368+369369+Note: Windows builds use `-Dc_std=gnu2x` instead of `gnu23` due to MinGW
370370+toolchain compatibility.
371371+372372+To verify:
373373+374374+```bash
375375+./build/ant.exe --version
376376+```
377377+378378+Windows builds require bundling the following DLLs alongside `ant.exe`:
379379+380380+- `libssl-3-x64.dll`
381381+- `libcrypto-3-x64.dll`
382382+- `libsodium-26.dll`
383383+384384+These are found in the MSYS2 MINGW64 bin directory
385385+(`/mingw64/bin/` or equivalent).
386386+387387+## Meson build options
388388+389389+Configure options are set via `meson setup` or `meson configure`:
390390+391391+| Option | Type | Default | Description |
392392+| ------------------- | ------- | --------- | ------------------------------------------ |
393393+| `static_link` | boolean | `false` | Statically link the final binary |
394394+| `build_timestamp` | string | (auto) | Build timestamp (defaults to current time) |
395395+| `tls_library` | combo | `openssl` | TLS backend: `openssl` or `mbedtls` |
396396+| `deps_prefix_cmake` | string | (empty) | Prefix path for cmake dependency lookup |
397397+398398+Standard Meson built-in options used by Ant:
399399+400400+| Option | Default | Description |
401401+| --------------- | --------- | --------------------------------- |
402402+| `buildtype` | `release` | Build type (release, debug, etc.) |
403403+| `optimization` | `3` | Optimization level (0-3) |
404404+| `c_std` | `gnu23` | C language standard |
405405+| `b_lto` | `true` | Link-time optimization |
406406+| `b_lto_threads` | `8` | LTO parallelism |
407407+| `strip` | `true` | Strip debug symbols from binary |
408408+| `b_sanitize` | `none` | Sanitizer (e.g. `address`) |
409409+410410+Example:
411411+412412+```bash
413413+meson setup build -Dtls_library=mbedtls -Dstatic_link=true --prefer-static
414414+```
415415+416416+## TLS library selection
417417+418418+Ant supports two TLS backends:
419419+420420+- **OpenSSL** (default): Widely available, used on all platforms by default.
421421+- **mbedTLS**: Lighter alternative, useful for embedded or constrained
422422+ environments. Currently only tested on macOS CI.
423423+424424+To build with mbedTLS:
425425+426426+```bash
427427+meson setup build -Dtls_library=mbedtls
428428+```
429429+430430+When using mbedTLS, the target triple in the version string will include
431431+`-mbedtls` as a suffix.
+7-7
CONTRIBUTING.md
···4455## Getting Started
6677-### Prerequisites
88-99-- C compiler with C23 support (GCC 14+ or Clang 18+)
1010-- Meson build system
1111-- Git
1212-- OpenSSL
1313-- libSodium
77+For the full list of prerequisites and platform-specific setup instructions, <br>
88+see [BUILDING.md](BUILDING.md#prerequisites).
1491510### Building from Source
1611···2116meson setup build
2217meson compile -C build
2318```
1919+2020+For detailed build instructions including debug builds, ASan builds, <br>
2121+ccache setup, and Windows/Linux/macOS specifics, see [BUILDING.md](BUILDING.md).
24222523## How to Contribute
2624···6563tests/ # JavaScript test files
6664vendor/ # External dependencies
6765```
6666+6767+For more information about Ant's internal structure, read the [Ant DeepWiki](https://deepwiki.com/theMackabu/ant).
68686969## Testing
7070
+3-9
README.md
···1616curl -fsSL https://ant.themackabu.com/install | MBEDTLS=1 bash
1717```
18181919-## Building from Source
2020-2121-```bash
2222-git clone https://github.com/theMackabu/ant.git && cd ant
1919+## Building Ant
23202424-meson subprojects download
2525-meson setup build
2626-meson compile -C build
2727-```
2121+See [BUILDING.md](BUILDING.md) for instructions on how to build Ant from source and a list of supported platforms.
28222923## Security
3024···3327## Contributing to Ant
34283529We welcome contributions through pull request. See [CONTRIBUTING.md](CONTRIBUTING.md) for more details. <br>
3636-For more information about the internals, read the [ant deepwiki](https://deepwiki.com/theMackabu/ant).
3030+For more information about Ant's internal structure, read the [Ant DeepWiki](https://deepwiki.com/theMackabu/ant).
37313832## Current project team members
3933
+148
tests/test_concurrent_scope.cjs
···11+// Test concurrent async scope isolation
22+// Verifies that closure variables survive across await boundaries
33+// when multiple async functions run concurrently
44+55+let passed = 0;
66+let failed = 0;
77+88+function assert(condition, msg) {
99+ if (condition) {
1010+ passed++;
1111+ } else {
1212+ failed++;
1313+ console.log('FAIL:', msg);
1414+ }
1515+}
1616+1717+// Test 1: Basic concurrent closure variable preservation
1818+async function worker(id, delayMs) {
1919+ const myId = id;
2020+ const myPrefix = 'worker-' + id;
2121+ const myArray = [id, id * 10, id * 100];
2222+ const myObj = { name: myPrefix, value: id * 42 };
2323+2424+ await new Promise(resolve => setTimeout(resolve, delayMs));
2525+2626+ // After await, all closure variables should be intact
2727+ assert(myId === id, `worker ${id}: myId was ${myId}, expected ${id}`);
2828+ assert(myPrefix === 'worker-' + id, `worker ${id}: myPrefix was ${myPrefix}`);
2929+ assert(myArray.length === 3, `worker ${id}: myArray.length was ${myArray.length}`);
3030+ assert(myArray[0] === id, `worker ${id}: myArray[0] was ${myArray[0]}`);
3131+ assert(myArray[2] === id * 100, `worker ${id}: myArray[2] was ${myArray[2]}`);
3232+ assert(myObj.name === myPrefix, `worker ${id}: myObj.name was ${myObj.name}`);
3333+ assert(myObj.value === id * 42, `worker ${id}: myObj.value was ${myObj.value}`);
3434+3535+ return myPrefix;
3636+}
3737+3838+// Test 2: Multiple sequential awaits with closure vars
3939+async function multiAwait(id) {
4040+ const step1 = 'step1-' + id;
4141+ await new Promise(resolve => setTimeout(resolve, 10));
4242+4343+ assert(step1 === 'step1-' + id, `multiAwait ${id} after 1st await: step1 was ${step1}`);
4444+4545+ const step2 = 'step2-' + id;
4646+ await new Promise(resolve => setTimeout(resolve, 10));
4747+4848+ assert(step1 === 'step1-' + id, `multiAwait ${id} after 2nd await: step1 was ${step1}`);
4949+ assert(step2 === 'step2-' + id, `multiAwait ${id} after 2nd await: step2 was ${step2}`);
5050+5151+ const step3 = 'step3-' + id;
5252+ await new Promise(resolve => setTimeout(resolve, 10));
5353+5454+ assert(step1 === 'step1-' + id, `multiAwait ${id} after 3rd await: step1 was ${step1}`);
5555+ assert(step2 === 'step2-' + id, `multiAwait ${id} after 3rd await: step2 was ${step2}`);
5656+ assert(step3 === 'step3-' + id, `multiAwait ${id} after 3rd await: step3 was ${step3}`);
5757+5858+ return [step1, step2, step3];
5959+}
6060+6161+// Test 3: Arrow function closures in async context
6262+async function closureTest(id) {
6363+ const captured = 'captured-' + id;
6464+ const transform = x => captured + '-' + x;
6565+6666+ await new Promise(resolve => setTimeout(resolve, 15));
6767+6868+ const result = transform('test');
6969+ assert(result === 'captured-' + id + '-test', `closureTest ${id}: transform result was ${result}`);
7070+ assert(captured === 'captured-' + id, `closureTest ${id}: captured was ${captured}`);
7171+7272+ return result;
7373+}
7474+7575+// Test 4: Nested async calls with closure isolation
7676+async function outer(id) {
7777+ const outerVar = 'outer-' + id;
7878+7979+ async function inner(suffix) {
8080+ const innerVar = outerVar + '-inner-' + suffix;
8181+ await new Promise(resolve => setTimeout(resolve, 5));
8282+ assert(innerVar === 'outer-' + id + '-inner-' + suffix, `inner ${id}/${suffix}: innerVar was ${innerVar}`);
8383+ assert(outerVar === 'outer-' + id, `inner ${id}/${suffix}: outerVar was ${outerVar}`);
8484+ return innerVar;
8585+ }
8686+8787+ const r1 = await inner('a');
8888+ assert(outerVar === 'outer-' + id, `outer ${id} after inner a: outerVar was ${outerVar}`);
8989+9090+ const r2 = await inner('b');
9191+ assert(outerVar === 'outer-' + id, `outer ${id} after inner b: outerVar was ${outerVar}`);
9292+9393+ return [r1, r2];
9494+}
9595+9696+// Test 5: Parameter preservation across await
9797+async function paramTest(a, b, c) {
9898+ const sum = a + b + c;
9999+ await new Promise(resolve => setTimeout(resolve, 10));
100100+101101+ assert(a + b + c === sum, `paramTest: sum was ${a + b + c}, expected ${sum}`);
102102+ assert(typeof a === 'number', `paramTest: a type was ${typeof a}`);
103103+ assert(typeof b === 'string', `paramTest: b type was ${typeof b}`);
104104+ assert(typeof c === 'boolean', `paramTest: c type was ${typeof c}`);
105105+106106+ return sum;
107107+}
108108+109109+// Launch all tests concurrently
110110+async function main() {
111111+ const promises = [];
112112+113113+ // Launch 5 concurrent workers with different delays
114114+ for (let i = 1; i <= 5; i++) {
115115+ promises.push(worker(i, 10 + i * 5));
116116+ }
117117+118118+ // Launch 3 concurrent multi-await chains
119119+ for (let i = 1; i <= 3; i++) {
120120+ promises.push(multiAwait(i));
121121+ }
122122+123123+ // Launch 3 concurrent closure tests
124124+ for (let i = 1; i <= 3; i++) {
125125+ promises.push(closureTest(i));
126126+ }
127127+128128+ // Launch 3 concurrent nested async tests
129129+ for (let i = 1; i <= 3; i++) {
130130+ promises.push(outer(i));
131131+ }
132132+133133+ // Launch concurrent param tests
134134+ promises.push(paramTest(42, 'hello', true));
135135+ promises.push(paramTest(99, 'world', false));
136136+137137+ await Promise.all(promises);
138138+139139+ console.log(`Results: ${passed} passed, ${failed} failed`);
140140+ if (failed > 0) {
141141+ console.log('FAIL: concurrent scope isolation test');
142142+ Ant.exit(1);
143143+ } else {
144144+ console.log('PASS: concurrent scope isolation test');
145145+ }
146146+}
147147+148148+main();