This chapter walks you through installing Mako, creating your first project, understanding the project structure, and setting up your editor.
To build and run Makori programs you need:
gcc or clang for linking (apt install gcc or apt install clang)Optional dependencies for full standard library support:
From a source checkout:
make install
This installs the mako binary to ~/.local/bin/mako and runtime headers to
~/.local/share/mako/runtime. Make sure ~/.local/bin is in your PATH.
Alternatively, use the install script directly:
./scripts/install.sh
Verify the installation:
mako version
# mako version mako0.6.2 darwin/arm64
The --version flag produces the same output:
mako --version
# mako version mako0.6.2 darwin/arm64
For verbose output including the git commit (when available):
mako version -v
If you want to build from the repository:
git clone https://github.com/mako-lang/mako.git
cd mako
cargo build --release
You can run the compiler directly without installing:
cargo run --release -- version
cargo run --release -- run examples/hello.mko
Then install when ready:
make install
cargo build --release
.\scripts\install.ps1
mako version
On Windows, clang must be on PATH. Install via choco install llvm or download
from the LLVM releases page. On macOS no external tools are
needed — the release binary ships with a bundled linker.
The compiler looks for runtime headers at $PREFIX/share/mako/runtime. If you
installed to a non-standard location, set the MAKO_RUNTIME environment
variable:
export MAKO_RUNTIME=/opt/mako/runtime
After installation, run makori doctor to verify your environment is correctly
configured:
mako doctor
This checks:
mako binary is in PATH and executableIf anything is misconfigured, makori doctor prints actionable guidance on how
to fix it.
Create a file called hello.mko:
fn main() {
print("hello from mako")
}
Run it:
mako run hello.mko
# hello from mako
That is the entire workflow. makori run compiles the source to a native binary
and executes it in one step.
For anything beyond a single file, use makori init to scaffold a project:
mako init myapp --name myapp
cd myapp
This creates:
myapp/
mako.toml -- project manifest
main.mko -- entry point
Run the generated project:
mako run main.mko
For an HTTP-oriented service layout:
mako init mysvc --backend
cd mysvc
mako run main.mko
This generates a project with HTTP server boilerplate and route handlers.
For a project with multiple members (library + application):
mako init myws --workspace
cd myws
mako check .
mako run -p app
The mako.toml file is the project manifest. It declares the project name,
version, dependencies, and build configuration:
[package]
name = "myapp"
version = "0.1.0"
[dependencies]
# path dependencies
utils = { path = "../utils" }
# registry dependencies (when available)
# json = "1.0"
[build]
# parallel compilation jobs
jobs = 8
When you run makori build main.mko in a directory with a mako.toml, the
binary name is derived from the package name.
| Command | What it does |
|---|---|
makori run file.mko |
Compile and execute in one step |
makori check file.mko |
Type-check without producing a binary (fast) |
makori build file.mko |
Compile to a native binary |
makori build --release file.mko |
Optimized build (-O3 -flto) |
makori build -j 8 file.mko |
Parallel object compilation |
makori test examples/testing |
Run the test suite |
makori fmt file.mko |
Format source to canonical style |
Incremental compilation is on by default. The compiler caches intermediate artifacts and only recompiles translation units that have changed. This makes the edit-compile-run loop fast even for larger projects.
For production deployment, always use --release:
mako build --release main.mko
This enables -O3 optimization and link-time optimization (-flto), producing
a smaller, faster binary. Static linking depends on the target and toolchain;
Linux musl is the documented static path, while glibc and platform libraries
may remain dynamic. See Cross-platform builds.
Here is a slightly more involved example showing functions, types, and control flow:
fn main() {
print("Fibonacci calculator")
let n = 10
print_int(fib(n))
let mut sum = 0
for i in range n {
sum = sum + fib(i)
}
print_int(sum)
}
fn fib(n: int) -> int {
if n <= 1 {
return n
}
return fib(n - 1) + fib(n - 2)
}
mako run fib.mko
# Fibonacci calculator
# 55
# 88
Most projects need more than one file. Makori uses packs and pulls:
name a unit with pack, bring it in with pull, and always call through the
pack name. When you makori run main.mko, the compiler pulls everything in.
Start with two files side by side:
// lib.mko
pack lib
fn add(a: int, b: int) -> int {
return a + b
}
fn greet(name: string) -> string {
return "hi " + name
}
// main.mko
pull "./lib.mko"
fn main() {
print_int(lib.add(2, 3))
print(lib.greet("mako"))
}
mako run main.mko
# 5
# hi mako
The default qualifier is the pulled file’s pack name (if not main),
otherwise the path basename. Symbols are not merged bare into the importer.
// main.mko
pull "./lib.mko" as lib
// dual: import lib "./lib.mko"
fn main() {
print_int(lib.add(2, 3))
}
Also available: blank pull _ "fmt" (load only) and dot pull . "./h.mko"
(bare names — specialized; use sparingly).
Say you're building a small service. Start with makori init, then add files
as you go:
mako init myservice --name myservice
cd myservice
myservice/
mako.toml
main.mko
routes.mko # you add this
db.mko # you add this
// db.mko
pack db
fn init() {
print("database ready")
}
fn count() -> int {
return 42
}
// routes.mko
pack routes
fn health(c: int) {
let _ = http_respond_json(c, 200, "{\"ok\":true}")
}
// main.mko
pull "./routes.mko"
pull "./db.mko"
fn main() {
db.init()
let fd = http_bind(8080)
print("listening on :8080")
// handle requests with routes.health(c) ...
}
When you have several pulls, group them into a single block:
pull (
"strings"
"./db.mko" as db
"./routes.mko" as routes
)
The formatter (makori fmt) rewrites multiple pull lines into this grouped form.
Pull std units by name (no ./ prefix) and always qualify:
pull "strings"
pull "path"
pull "net/http"
fn main() {
print(strings.trim(" hello "))
print(strings.concat(strings.split("a,b", ","), "-"))
print_int(int(path.matches("*.mko", "main.mko")))
}
join and match are keywords, so the equivalents are concat and
matches. Full index: STDLIB.md · book
ch07-stdlib.
File imports work great within a single project. When you want to share code across projects, or your codebase grows large enough to need separate build units, reach for packages and workspaces -- covered in Chapter 10: Packages.
A Makori extension is available that provides:
.mko filesmakori check for inline diagnosticsmakori fmtInstall it from the extensions marketplace or point your editor at the .mko
grammar file in the repository under editors/vscode/.
Add .mko filetype detection to your configuration:
autocmd BufRead,BufNewFile *.mko set filetype=mako
For LSP integration, configure the Makori language server in your LSP client settings.
makori fmt on save. This keeps all code in canonical
style and avoids formatting debates.makori check for rapid feedback without a full build.file:line:col: message format will show
inline errors.# Check your installation
mako version
mako doctor
# Create and run a project
mako init hello --name hello
cd hello
mako run main.mko
# Type-check without building
mako check main.mko
# Build a release binary
mako build --release main.mko
# Format your code
mako fmt main.mko
# Run tests
mako test examples/testing
"clang: command not found" (Linux/Windows only)
On macOS, the native backend uses a bundled linker — clang is not needed.
On Linux: sudo apt install gcc (or clang). On Fedora: sudo dnf install gcc.
On Windows: install LLVM or choco install llvm.
"runtime headers not found"
Either run make install again or set MAKO_RUNTIME to point at the runtime
directory.
"permission denied" on ~/.local/bin/mako
Ensure ~/.local/bin exists and is writable:
mkdir -p ~/.local/bin
make install
Build cache issues
If you suspect stale cache artifacts, clean and rebuild:
mako build --clean main.mko
You now have Mako installed, know how to create projects, and can build and run programs. The next chapter is a comprehensive tour of the language syntax.
Next: Language Tour.