Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Project Layout

A Flint project is simple by design.

my_project/
  flint.toml       ← manifest
  src/
    main.fl        ← entry point
    drivers/
      display.fl   ← local module
      sensor.fl    ← local module
  build/           ← generated by flint build (git-ignore this)

The Manifest (flint.toml)

flint.toml is TOML and lives at the project root. The minimal required fields are:

name = "my_project"
version = "0.1.0"
edition = "2026"
target = "rp2040"
board = "pico"
FieldDescription
nameProject name. Used as the artifact filename.
versionSemver project version.
editionSource compatibility year. Use 2026.
targetThe chip to compile for (e.g., rp2040).
boardThe board package (e.g., pico).

Optional Manifest Fields

# Allow recursive function calls on MCU targets.
# Disabled by default on MCU targets to catch stack-risk bugs.
allow-recursion = true

Source Files

All source lives under src/. Files use the .fl extension. Each file is exactly one module.

The entry point is always src/main.fl. Modules are imported with use using their path relative to src/:

// src/main.fl
use drivers/display
use drivers/sensor

fn main() -> never {
    display.init()
    let temp = sensor.read_celsius()
    display.show_temp(temp)
    loop {}
}
// src/drivers/display.fl
pub fn init() -> () {
    // ...
}

pub fn show_temp(temp_c: i32) -> () {
    // ...
}

The file src/drivers/display.fl maps to the module path drivers/display. Its exported functions are accessed as display.init(), display.show_temp(...).

Module Rules

  • One file, one module. No module declarations in source.
  • Import paths use /, not . or ::.
  • The last path segment is the default module name: use drivers/display imports as display.
  • Use as to rename: use drivers/display as screen.
  • No wildcard imports (use foo/* is not supported).
  • No relative imports (./foo or ../foo are not supported).

Build Output

flint build writes artifacts into build/ inside your project:

build/
  my_project.uf2
  my_project.elf
  my_project.bin

The build/ directory is generated. Add it to your .gitignore.

PIO Files

RP2040 PIO programs live anywhere under src/ with a .pio extension:

src/
  main.fl
  drivers/
    blink.pio

Reference them at compile time through micro/pio:

use micro/pio
let program = pio.program_file("drivers/blink.pio")?

The compiler assembles the PIO program during the build.

Manifestless Builds

You can build a single file or directory without a flint.toml, but you must specify the target explicitly:

flint build src/main.fl --target rp2040
flint build src/ --target rp2040

Manifestless builds are useful for quick experiments. For real projects, always use a manifest.