std/project

The receiver type of project.trb - Project, Dependencies, Program, ScriptFamily, Profile, Test, Tasks, Workspace, Registry and Source.

The generated reference of std/project has every public construct with its signature, its doc comment and its examples.

std/project is the vocabulary of project.trb. A project file is a receiver script against Project, so everything a project can say about itself is a var field or a method of the types here, and nothing else is needed to write one: a setting is written name = "acme/shop", a section tasks { ... } and a program program "migrate", entry: "tools/migrate.trb". The types are ordinary data, not native - a project file is deterministic and has no IO, so evaluating it is nothing but running these members.

What a package produces is not in this vocabulary at all: the names of its files say it (src/main.trb, src/lib.trb, *.test.trb), and project.trb has the table.

Import#

project.trb is loaded as a receiver script against Project, so it never writes a use for these types itself; a tool that reads a manifest programmatically imports them like anything else.

use Project, Dependencies, Program, ScriptFamily, Profile, Test, Tasks, Workspace, Registry, Source from "std/project"
use Project from "std/project"

var project = Project()
project.name = "acme/shop"
print project.name

Declarations#

Project#

type Project {
  var name: String = ""
  var version: String = ""
  var language: String = ""
  var description: String = ""
  var license: String = ""
  var repository: String = ""
  var prelude: String = "std/prelude"
  var dependencies: Dependencies = Dependencies()
  var test: Test = Test()
  var tasks: Tasks = Tasks()
  var workspace: Workspace = Workspace()
  protected var authorNames: List<String> = []
  protected var keywordNames: List<String> = []
  protected var registries: List<Registry> = []
  protected var sources: List<Source> = []
  protected var programs: List<Program> = []
  protected var families: List<ScriptFamily> = []
  protected var profiles: List<Profile> = []
  var fn authors(...names: String)
  var fn keywords(...words: String)
  var fn registry(owner: String, url: String)
  var fn source(package: String, path: String = "", git: String = "", revision: String = "", archive: String = "", hash: String = "")
  var fn program(name: String, entry: String = "", output: String = "")
  var fn scripts(pattern: String, receiver: String, from: String)
  var fn profile(name: String, configure: (var self: Profile) => Void)
  fn settings(): String
}

The receiver of project.trb. A setting is a var field (name = "acme/shop" writes it), a section is a field configured in place (tasks { ... }), and only what is more than that is a method (authors, keywords, registry, source, program, scripts, profile). name is owner/name - owners are verified namespaces of a registry, so a bare name is not publishable. keywords are the words a registry's search finds the package by, at most five of 2 to 24 characters of a-z, 0-9 and -, which torb publish checks. The fields are readable, which is what lets a project file compute from what it already said: description = "The {name} package".

program declares a Program, scripts a ScriptFamily and profile configures a Profile. There is no build: a manifest that writes build { } does not check.

Dependencies#

type Dependencies {
  protected var runtimeRequirements: List<String> = []
  protected var developmentRequirements: List<String> = []
  var fn runtime(...requirements: String)
  var fn development(...requirements: String)
}

runtime is what dependents get; development is tests and tools and is never part of it. A requirement is written as it is published ("acme/http:^1.2.3"), because the version is the package manager's business and the project file only names what it wants.

Program#

type Program {
  name: String
  entry: String = ""
  output: String = ""
}

A program of the package beyond the src/main.trb that needs no line, declared with Project.program: program "migrate", entry: "tools/migrate.trb". entry is the file whose top-level code the program is, relative to the project; a line without one renames the default program (program "torb"). output is where the binary goes, relative to the project and taken literally; empty is build/<profile>/<name>. The toolchain reads the three before it can run anything, so each is a plain string, and name is lowercase letters, digits and -.

program "migrate", entry: "tools/migrate.trb", output: "dist/migrate"

ScriptFamily#

type ScriptFamily {
  pattern: String
  receiver: String
  from: String
}

A family of receiver scripts, declared with Project.scripts: scripts "config/*.trb", receiver: "ServerConfig", from: "./src/server-config". pattern is a path relative to the project's directory that ends in .trb, with / as the separator; * matches any run of characters inside one segment, so config/*.trb matches config/server.trb and not config/nested/server.trb. receiver is the name of the type each matched file configures, and from the module that declares it, written as the path of a use. The line only names them: nothing imports the module, and a pattern that matches no file is no problem.

The toolchain reads the three before it can run anything, so each is a plain string - a computed one is refused where it is written, and the line is never run - and a pattern that is not a path relative to the project that ends in .trb (./a.trb, ../a.trb, /a.trb, a\b.trb, a/**/b.trb, a?.trb, a.txt, an empty one) is a problem of the manifest at the pattern. A project without a scripts line reads and prints back as it always did.

scripts "config/*.trb", receiver: "ServerConfig", from: "./src/server-config"

Profile#

type Profile {
  name: String
  var optimize: Int = 1
  var debugInformation: Bool = false
  var panicFrames: Bool = true
  static fn named(name: String): Self
}

How one of the two profiles builds, configured with Project.profile. name is dev or release and there is no third. optimize is the level of the C compiler, 0 to 3 - 1 in dev and 2 in release. debugInformation makes the binary carry debug information for a debugger. panicFrames - true in dev, false in release - says whether a panic of a native binary prints the frames that led to it below its site; an MSVC build keeps none, and the VM prints the site alone. Profile.named is the profile where no block says otherwise, and the block of profile starts from it:

profile "release" {
  optimize = 3
  debugInformation = true
}

Test#

type Test {
  var coverageThreshold: Int = 0
}

coverageThreshold is the share of lines a test run has to cover, in percent, and 0 asks for nothing. torb test reads it: it measures the lines of the package's src/ in the VM and fails below the share (see Coverage); a value outside 0 to 100 is a problem of the manifest. Which files are tests is not a setting: a file called *.test.trb is one wherever it lies in the package.

Tasks#

type Tasks {
  var workers: Int = 0
  var blocking: Int = 0
}

How the program's tasks run: workers threads run its tasks, the core count where the line is left out, and blocking threads run what blocks (offload), 4 where it is left out. TORB_WORKERS and TORB_BLOCKING override both where the program runs, so a machine can be told without a rebuild. 0 is "not said"; a number the toolchain reads has to be 1 to 1024, and workers = 0 is refused rather than read as "decide for me".

tasks {
  workers = 4
  blocking = 8
}

Workspace#

type Workspace {
  protected var memberPatterns: List<String> = []
  var fn members(...patterns: String)
}

A project that consists of several projects. Every member is an ordinary project with its own project.trb; a pattern is a directory or directory/* for every project directly below it.

Registry#

type Registry {
  owner: String
  url: String
}

An owner bound to a registry, so a public package can never take the place of a private one.

Source#

type Source {
  package: String
  path: String = ""
  git: String = ""
  revision: String = ""
  archive: String = ""
  hash: String = ""
}

Where one package comes from instead of the registry its owner is bound to: source "acme/y", path: "../y". The package manager resolves a path: source, an archive: source (with hash:, the tree hash of the unpacked archive) and a git: source (with revision:, a tag, a branch or a commit, locked by its commit; project.lock.trb).

  • project.trb - what the toolchain reads out of these settings, and what the names of the files decide instead.
  • std/sandbox - Sandbox, the mechanism project.trb is loaded through.
  • The standard library - the other packages.
Esc