Skip to content

Building and Usage

Andrew Lind edited this page Jun 25, 2026 · 5 revisions

Requirements

  • Rust (stable; install via rustup)
  • A C++98 toolchain to build the generated output. The development validation gate uses g++ -std=c++98; the production target is Visual C++ 6.0 up.

Building

cargo build            # debug binary at target/debug/hatchet
cargo build --release  # optimized binary at target/release/hatchet
cargo test             # unit tests, header/body codegen checks, and the C++98 compile+run gates

Usage

# Transpile a whole project — point --src at its root directory; Hatchet crawls it
# recursively for .hx. The C++ namespace of each file follows its Haxe `package`, and
# the project root is inferred from that package.
hatchet --src path/to/project --out path/to/output --force

# A glob works too (expanded by Hatchet itself, so quote it on shells that would
# otherwise expand it). Mix files, dirs, and globs freely:
hatchet --src src/*.hx --out path/to/output

# Transpile a single file — pass its dependencies too (superclasses, native stubs),
# since the listed sources are the entire resolution scope:
hatchet --src src/Button.hx src/Widget.hx --out path/to/output

# Resolve against native stubs without transpiling them (--include is resolve-only)
hatchet --src src --include native --out path/to/output

# Amalgamate everything into one self-contained, header-only library (no .cpp, no StdAfx.h)
hatchet --src src --header-only MyLib --out path/to/output

# Preview on stdout, or validate without writing anything:
hatchet --src src/Button.hx src/Widget.hx --stdout
hatchet --src . --dry-run

# Run interactively (prompts for a source and a target dir) when --src is omitted:
hatchet

--src accepts any mix of single .hx files, directories (crawled recursively for .hx), and globs (*, ?, ** — e.g. src/*.hx or src/**/*.hx). Globs are expanded by Hatchet itself, so quoting them to bypass shell expansion works. The full expanded set, plus any --include inputs, is the entire resolution scope, so a file's dependencies (superclasses, extern stubs) must be reachable in it — crawl the project root to pull everything in. Each file's project root — the base for the output layout and relative includes — is inferred from its package declaration (the file's directory minus its package path).

Native stubs (extern / @:native declarations that name hand-written C++) are best supplied via --include rather than --src: like --src it accepts files, directories, and globs and adds them to the resolution scope, but the files it names are resolve-only — never transpiled (the Haxe equivalent of passing a C/C++ header). Only their @:include directives propagate into the generated output. Anything reached through --include is simply not a transpilation target, so a stray non-extern class there is silently skipped, not emitted.

Flag Description
--src, -s <PATH>... Haxe sources to transpile — any mix of .hx files, directories (crawled recursively), and globs (*/?/**); prompted if omitted. Together with --include, the full resolution scope
--include <PATH>... Resolve-only inputs (files/dirs/globs, like --src): added to the resolution scope so the --src files' native references resolve and their @:include headers propagate, but never transpiled — the Haxe equivalent of a C/C++ header. A non-extern file reached here is silently not emitted (it is not a transpilation target)
--header-only <NAME> Amalgamate all --src content into one self-contained header <NAME>.h (a trailing .h is stripped): the prelude is inlined, every class and module-level free function is emitted with inline bodies, and no .cpp or separate prelude header is produced — a drop-in single-header library. Resolve-only --include stubs are not folded in (only their @:includes are hoisted). Free-function names must be unique within a package (one shared namespace); only @cexport extern "C" exports remain unsupported (an exported symbol needs an object file)
--out, -o <DIR> Output directory (defaults to the inferred project root; ignored with --dry-run/--stdout). Generated files mirror the source package layout; includes that point at external dependencies (a native library, a sibling project) are re-pointed at the dependency's real location when needed, so --out resolves from any directory
--force Overwrite existing generated files (ignored with --dry-run)
--dry-run Transpile and report info/warnings/errors only — write nothing. Takes precedence over --stdout/-o/--force
--stdout Write generated C++ to stdout instead of files (status goes to stderr)
--stdafx <NAME> Stem of the prelude source/header (default StdAfxStdAfx.h; e.g. MyGameMyGame.h)
--export-macro <PREFIX> Prefix for the portable export macros wrapped around @cexport functions and @libexport classes (default HATCHETHATCHET_EXPORT/HATCHET_CALL/HATCHET_CLASS)
--depth <N> Max expression-nesting depth at which a buried Null<T> call is auto-extracted into a freed local instead of warned about (default 1; e.g. 2 auto-extracts if (GetEdge(e) == null))
--no-traces Strip all trace(...) calls from the generated C++ (lowered to no-ops, arguments not evaluated), mirroring hxcpp's -D no-traces

Every generated file opens with a provenance comment naming the repository and the transpiler version — // Generated by Hatchet (https://github.com/andrewglind/hatchet) v<version>, the same version string --version reports. It is a // comment ahead of the include guard, so it never affects compilation.

A Main.hx is never transpiled — it is treated as the hxcpp entry point only.

Clone this wiki locally