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

Program entrypoints and native compilation

Running and linking

Plenty compiles ahead of time. Running a file compiles a temporary native executable, runs it, and removes it afterward. Both running and compiling require a cc-compatible linker driver. The default is cc on PATH; add --linker clang or --linker /path/to/driver to select another. Repeat --link-arg ARG for extra native link arguments. Checking needs no linker. The Rust runtime is packaged with Plenty; compiling Plenty programs needs neither cargo nor rustc.

Entrypoints and exit status

Execution starts by calling main once. Every binary application must declare main with no parameters. It can return (), i32, Result[(), E], or Result[i32, E]. Ok(()) produces exit status zero and Ok(status) uses that status. An Err is reported on standard error, then dropped, and the program exits with status one. For example, a main that returns the error from reading a missing file prints error: main returned IoError.System(2): No such file or directory. The error is printed once, when main returns it, not at each ? on the way. The () form finishes successfully with exit status zero. The i32 form returns a process exit status: zero means success, and nonzero means failure. Use an i32 literal such as 0i32 or 1i32; return annotations also guide unsuffixed literals.

Keep executable statements inside functions. Module scope contains def, class, enum, and type declarations, plus imports. Bindings inside main are local to it. The modules part explains imports and pub visibility.

Owned locals are dropped before the program exits, including when main returns a nonzero status. Operating systems limit the range of observable exit statuses; use small nonnegative codes for portable command-line programs.

You can also choose the successful process status explicitly:

def main() -> Result[i32, IoError]:
    print("ready")?
    Ok(0i32)
ready

Calling a function at module scope is an error, even if main is also declared:

def main() -> ():
    print("ready").unwrap()

main()
executable statements are not allowed at module scope

Keeping an executable or linking externally

Use --compile when you want to keep the executable and run it repeatedly without compiling again. The executable does not need Plenty installed.

For an external build system, use plenty --emit-object hello.plenty -o hello.o and plenty --emit-runtime runtime. Link the object with runtime/libplenty_runtime.a followed by the arguments in runtime/link-args.txt. These two commands do not invoke a linker. They emit a complete application, including its imports; ordinary pub functions are not C exports. Native compilation currently supports x86_64-unknown-linux-gnu. Use plenty --print-target to inspect the packaged target. An explicit --target TRIPLE must match it; choosing a linker does not enable cross-compilation.