Language · Building & tooling
Building Eskiu from Source
Requirements
| Dependency | Minimum | Tested |
|---|---|---|
| LLVM | 21 | 22.x |
| CMake | 3.20 | 3.x |
| C++ compiler | C++17 (clang++ recommended, g++ works) | clang++ 17+ |
| git | any | n/a |
LLVM is the only non-trivial dependency. The compiler uses the support, core, and irreader component libraries.
macOS
Install dependencies
brew install llvm cmake
Homebrew installs LLVM into a versioned prefix (e.g. /opt/homebrew/opt/llvm) and does not add it to PATH by default. Export the necessary paths before building:
export PATH="$(brew --prefix llvm)/bin:$PATH"
export LLVM_DIR="$(brew --prefix llvm)/lib/cmake/llvm"
Add these to your shell profile (~/.zshrc or ~/.bash_profile) to make them permanent.
Homebrew's llvm formula tracks the newest release (LLVM 23 at the time of writing). Eskiu builds against it, but CI and the release binaries use LLVM 22. To match them exactly, install llvm@22 and use $(brew --prefix llvm@22) in the two lines above.
Build
git clone https://github.com/doranteseduardo/eskiu.git
cd eskiu
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -- -j$(sysctl -n hw.logicalcpu)
Expected output (last few lines):
[ 85%] Building CXX object CMakeFiles/eskiuc.dir/codegen/codegen_expr.cpp.o
[100%] Linking CXX executable eskiuc
[100%] Built target eskiuc
The compiler binary is at build/eskiuc.
Linux (Ubuntu / Debian)
Install dependencies
sudo apt-get update
sudo apt-get install -y llvm-22-dev clang-22 cmake git
For Ubuntu 22.04 or older, the LLVM 22 packages are in the LLVM apt repository:
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 22
sudo apt-get install -y llvm-22-dev
Build
git clone https://github.com/doranteseduardo/eskiu.git
cd eskiu
cmake -S . -B build \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_DIR=/usr/lib/llvm-22/lib/cmake/llvm \
-DCMAKE_CXX_COMPILER=clang++-22
cmake --build build -- -j$(nproc)
Linux (Alpine)
Install dependencies
apk add llvm22-dev cmake clang22 git make
Build
git clone https://github.com/doranteseduardo/eskiu.git
cd eskiu
cmake -S . -B build \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_DIR=/usr/lib/llvm22/lib/cmake/llvm \
-DCMAKE_CXX_COMPILER=clang++
cmake --build build -- -j$(nproc)
Build Options
Debug vs Release
# Release: optimized binary, suitable for benchmarks
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
# Debug: unoptimized, assertions enabled, better stack traces
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug
Incremental builds
After changing source files, just re-run the build step; CMake tracks dependencies:
cmake --build build -- -j$(nproc)
Clean rebuild
Delete the build directory and start over:
rm -rf build
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -- -j$(nproc)
Verify the Build
Version check
./build/eskiuc --version
Expected output:
Eskiu 0.9.2 (LLVM 22.x.x)
The LLVM version will reflect whichever version is installed on the host.
Smoke test
./build/eskiuc examples/hello.esk --test-codegen
Expected output (LLVM IR for hello.esk):
; ModuleID = 'eskiu_module'
source_filename = "eskiu_module"
@0 = private unnamed_addr constant [19 x i8] c"Hello from Eskiu!\0A\00"
@1 = private unnamed_addr constant [12 x i8] c"Result: %d\0A\00"
declare i32 @printf(ptr, ...)
define i32 @add(i32 %a, i32 %b) {
entry:
...
}
define i32 @main() {
entry:
...
}
The exact IR body will vary with LLVM version, but the module must contain @printf, @add, and @main.
Troubleshooting
LLVM not found
CMake Error: Could not find a package configuration file provided by "LLVM"
Point CMake at the correct LLVM cmake directory:
cmake -S . -B build -DLLVM_DIR=/path/to/llvm/lib/cmake/llvm
Common paths:
| Platform | Path |
|---|---|
| macOS (Homebrew arm64) | /opt/homebrew/opt/llvm/lib/cmake/llvm |
| macOS (Homebrew x86) | /usr/local/opt/llvm/lib/cmake/llvm |
| Ubuntu apt llvm-22 | /usr/lib/llvm-22/lib/cmake/llvm |
| Alpine apk llvm22 | /usr/lib/llvm22/lib/cmake/llvm |
You can also run llvm-config --cmakedir (substituting the versioned binary name if needed) to get the correct path:
llvm-config-22 --cmakedir
C++17 errors
If the system default compiler does not support C++17, specify the compiler explicitly:
cmake -S . -B build \
-DCMAKE_CXX_COMPILER=clang++-22 \
-DCMAKE_C_COMPILER=clang-22
Linker errors: undefined LLVM symbols
The build links support, core, and irreader. If you see undefined symbols from LLVM:
- Confirm the installed LLVM version matches the headers used at configure time (
llvm-config --version). - On Ubuntu, ensure you installed
llvm-22-dev(not justllvm-22); the-devpackage contains the static libraries. - On Alpine,
llvm22-devis the correct package name;llvm22alone does not ship the.aarchives.
Running Tests
The automated suite is driven by tests/run.sh, which compiles, links, and runs every
tests/*.esk case (matching stdout against *.expected, smoke-running the rest, and
checking that tests/errors/*.esk are rejected). eskiuc links each test itself with
no -l flags, so the libraries programs imply (#pragma link, the C++ exception
runtime, pthread) are exercised too:
tests/run.sh # full suite against build/eskiuc
ESKIUC=/path/eskiuc tests/run.sh # point at a specific compiler
CI runs the suite three ways: plain, then under UBSan and ASan (SANITIZE=ubsan /
SANITIZE=asan) as hardening gates, plus a generative fuzzer
(tests/fuzz/eskiu_fuzz.py) that mutates programs and fails on any compiler crash,
IR-verifier failure, or O0-vs-O2 runtime divergence (a differential oracle); a
golden-IR oracle guards against unintended codegen changes.
The four --test-* modes below expose individual compiler phases for manual inspection.
--test-lexer
Tokenizes the input and prints every token with its type, value, and source location.
./build/eskiuc examples/hello.esk --test-lexer
Expected output (truncated):
Tokenizing: examples/hello.esk
========================================================
Line 1, Col 1 EXTERN 'extern'
Line 1, Col 8 INT 'int'
Line 1, Col 12 IDENT 'printf'
Line 1, Col 18 LPAREN '('
Line 1, Col 19 STRING 'string'
...
========================================================
Total tokens: 57
--test-parser
Parses the token stream and prints the AST in indented form.
./build/eskiuc examples/hello.esk --test-parser
Expected output (truncated):
Parsing: examples/hello.esk
========================================================
Program
ExternDecl: printf -> int
Parameters:
string fmt
... ...
FunctionDecl: add -> int
Parameters:
int a
int b
Body:
BlockStmt
ReturnStmt
BinaryExpr: +
Left:
IdentExpr: a
Right:
IdentExpr: b
FunctionDecl: main -> int
...
--test-typechecker
Runs semantic analysis. Prints Type checking succeeded! on success, or typed errors on failure.
./build/eskiuc examples/hello.esk --test-typechecker
Expected output on a valid file:
Type checking: examples/hello.esk
========================================================
========================================================
Type checking succeeded!
Example error output for a type mismatch:
error: type mismatch in return: expected 'int', got 'float'
--test-codegen
Runs the full pipeline through LLVM IR emission and prints the IR to stdout.
./build/eskiuc examples/hello.esk --test-codegen
A non-empty IR module with no error: lines on stderr indicates a passing build.
To batch-test all .esk files in the examples directory:
for f in examples/*.esk; do
echo "=== $f ==="
./build/eskiuc "$f" --test-typechecker
done
eskiu