trident
The manifest: trident.toml
Every key of trident.toml, how sources and assets are listed, and the three ways a project can choose its entry point.
since 0.1.0-alpha.1linux
Description
A project is described by a file named trident.toml in the project's root directory. The name is
fixed. trident reads it; the compiler never does. The format is a small subset of TOML: string
values, lists of strings (which may continue over several lines), true and false, # comments,
and repeated [[dep]] tables.
name = "app"
entry = "main.lev" # a function name, or a file ending in .lev
sources = ["*.lev", "models/*.lev"] # globs expand alphabetically
assets = ["views/**", "schema.sql"] # files a comptime import() may read
version = "0.1.0" # optional
out = "app" # optional
[[dep]] # repeat for each dependency
path = "../jsonlib"
as = "Json"
version = "1.0.0"
dev = false
| Key | Meaning |
|---|---|
name |
The project's name. It is also the default name of the executable. |
entry |
Where the program starts: a function name, or the name of a source file ending in .lev. Optional. |
sources |
The source files, as paths relative to the manifest. Required, and it must list at least one file. |
assets |
Files that comptime import() calls may read. Optional. |
version |
The project's own version, used when the project is published. Optional. |
out |
The name of the executable that trident build writes. Optional; the default is name, or a.out when there is no name either. |
[[dep]] |
One dependency each; see trident.dependencies. |
An unknown key, an unknown table, a missing sources list or an unterminated string is reported as an
error with the line number, and nothing is built.
Sources
Each entry of sources is a path relative to the directory of the manifest. A * in the last path
segment matches files in that one directory, so "models/*.lev" lists every .lev file in
models. The matches of one pattern are sorted alphabetically, and the patterns themselves are
used in the order you wrote them. The order matters in one case, which is a project without an entry
point (below). A listed file that does not exist is an error.
Entry points
The three forms of entry decide which code runs.
- No
entry: script mode. The top-level statements of all the source files run, one file after another in the order ofsources. Use it for small programs. - A function name, such as
entry = "main". The program starts by calling that function. No source file may have top-level statements; all code lives in functions and classes. - A file name, such as
entry = "main.lev". The top-level statements of that file are the program. The other files may only contain declarations.
trident decides which of the two named forms an entry is: a name that ends in .lev is a file,
anything else is a function. It records the decision in the build plan, so the compiler never guesses
from a name. A file or function that breaks these rules is a compile error that names the offending
statement, for example top-level code outside the entry file.
Script mode: top-level statements run in order
console.writeln("first");
console.writeln("second");
first
second
A function entry looks like this. With entry = "main" and this file as the only source,
trident run prints started in main:
A function entry point
void main() {
console.writeln("started in main");
}
Assets
assets declares the files that the program is allowed to read at compile time with import(path).
Each item is a literal path, a glob, or a recursive glob such as "views/**" that matches a whole
tree. Assets are paths relative to the manifest. trident hashes each one and records it in the plan.
A pattern that matches no files is a warning; a literal path that does not exist is an error. A
program that imports a file that is not declared fails to compile with a message that says to add it to
assets.
A bare source file with no manifest is a project of one file, so the compiler's project questions
(--imports, --graph, --namespaces, --why; see lang.compiler-cli) work on it as well.
Rules
- The file is named
trident.tomland sits at the project root. sourcesis required and must name at least one file.- Keys other than
name,entry,sources,assets,versionandoutare errors, and so are tables other than[[dep]]. - An entry ending in
.levis a file entry; anything else is a function entry. - With a file entry, only that file may have top-level statements. With a function entry, no file may.
trident add,removeandupdaterewrite the whole manifest. Comments and layout are not preserved.
Examples
A project with a named output, several source folders and a function entry:
name = "notes"
entry = "main"
sources = ["main.lev", "models/*.lev", "util/*.lev"]
out = "notes-cli"
A project that embeds its HTML templates:
name = "site"
entry = "main.lev"
sources = ["main.lev"]
assets = ["views/**", "style.css"]
Notes
- A
sourcespattern with**does not search directories recursively; list each directory you want.**has that meaning only inassets. - A namespace does not have to match the directory its file sits in. If you want that convention
checked,
leviathan --lint-namespacesreports every file whose folder is not the end of the namespace it opens. It is opt-in and no build applies it.
See also
- Two tools: trident and leviathan — How the package manager and the compiler divide the work, what the build plan between them is, and the commands that build and run a project.
- Dependencies — Declaring local and repository dependencies, renaming a dependency's namespace with
as, development-only dependencies, and the rule that you may only use what you declared. - The leviathan command line — Every option of the
leviathancompiler, grouped by what it does, with the exit statuses and how arguments reach your program. - import() — comptime file inclusion —
std::import(path)reads a project file at compile time and folds to its contents as acomptimestring. - Namespaces — Group declarations under a name, reopen a namespace to add to it, nest namespaces, and reach members with
::.