Type WorkMap

type WorkMap = LinearMap<WorkKey, ~str>

Struct Context

struct Context {
    db: @Database,
    logger: @Logger,
    cfg: @json::Object,
    freshness: LinearMap<~str, @pure fn(&str, &str) -> bool>,
}

Struct Database

struct Database {
    a: (),
}

Struct Exec

struct Exec {
    discovered_inputs: WorkMap,
    discovered_outputs: WorkMap,
}

Struct Logger

struct Logger {
    a: (),
}

Struct Prep

struct Prep {
    ctxt: @Context,
    fn_name: ~str,
    declared_inputs: WorkMap,
    declared_outputs: WorkMap,
}

Struct Work

struct Work <T: Owned>{
    prep: @mut Prep,
    res: Option<Either<T, PortOne<(Exec, T)>>>,
}

Struct WorkKey

struct WorkKey {
    kind: ~str,
    name: ~str,
}

This is a loose clone of the fbuild build system, made a touch more generic (not wired to special cases on files) and much less metaprogram-y due to rust's comparative weakness there, relative to python.

It's based around imperative bulids that happen to have some function calls cached. That is, it's just a mechanism for describing cached functions. This makes it much simpler and smaller than a "build system" that produces an IR and evaluates it. The evaluation order is normal function calls. Some of them just return really quickly.

A cached function consumes and produces a set of works. A work has a name, a kind (that determines how the value is to be checked for freshness) and a value. Works must also be (de)serializable. Some examples of works:

kind name value
cfg os linux
file foo.c
url foo.com

Works are conceptually single units, but we store them most of the time in maps of the form (type,name) => value. These are WorkMaps.

A cached function divides the works it's interested up into inputs and outputs, and subdivides those into declared (input and output) works and discovered (input and output) works.

A declared input or output is one that is given to the workcache before any work actually happens, in the "prep" phase. Even when a function's work-doing part (the "exec" phase) never gets called, it has declared inputs and outputs, which can be checked for freshness (and potentially used to determine that the function can be skipped).

The workcache checks all works for freshness, but uses the set of discovered outputs from the previous exec (which it will re-discover and re-record each time the exec phase runs).

Therefore the discovered works cached in the db might be a mis-approximation of the current discoverable works, but this is ok for the following reason: we assume that if an artifact A changed from depending on B,C,D to depending on B,C,D,E, then A itself changed (as part of the change-in-dependencies), so we will be ok.

Each function has a single discriminated output work called its result. This is only different from other works in that it is returned, by value, from a call to the cacheable function; the other output works are used in passing to invalidate dependencies elsewhere in the cache, but do not otherwise escape from a function invocation. Most functions only have one output work anyways.

A database (the central store of a workcache) stores a mappings:

(fn_name,{declared_input}) => ({declared_output},{discovered_input}, {discovered_output},result)

Implementation of core::cmp::Eq for WorkKey

Method eq

fn eq(__other: &WorkKey) -> bool

Method ne

fn ne(__other: &WorkKey) -> bool

Implementation of to_bytes::IterBytes for WorkKey

Method iter_bytes

fn iter_bytes(lsb0: bool, f: to_bytes::Cb)

Implementation for WorkKey

Method new

fn new(kind: &str, name: &str) -> WorkKey

Implementation for Database

Method prepare

fn prepare(_fn_name: &str, _declared_inputs: &const WorkMap,
           _declared_outputs: &const WorkMap) ->
 Option<(WorkMap, WorkMap, ~str)>

Method cache

fn cache(_fn_name: &str, _declared_inputs: &WorkMap,
         _declared_outputs: &WorkMap, _discovered_inputs: &WorkMap,
         _discovered_outputs: &WorkMap, _result: &str)

Implementation for Logger

Method info

fn info(i: &str)

Implementation for Context

Method new

fn new(db: @Database, lg: @Logger, cfg: @json::Object) -> Context

Method prep

fn prep<T: Owned Encodable<json::Encoder> Decodable<json::Decoder>>(fn_name:
                                                                        &str,
                                                                    blk:
                                                                        &fn
                                                                            (@mut Prep)
                                                                            ->
                                                                                Work<T>)
 -> Work<T>

Implementation for Prep

Method declare_input

fn declare_input(kind: &str, name: &str, val: &str)

Method declare_output

fn declare_output(kind: &str, name: &str, val: &str)

Method is_fresh

fn is_fresh(cat: &str, kind: &str, name: &str, val: &str) -> bool

Method all_fresh

fn all_fresh(cat: &str, map: WorkMap) -> bool

Method exec

fn exec<T: Owned Encodable<json::Encoder> Decodable<json::Decoder>>(blk:
                                                                        ~fn
                                                                            (&Exec)
                                                                            ->
                                                                                T)
 -> Work<T>

Implementation for Work<T>

Method new

fn new(p: @mut Prep, e: Either<T, PortOne<(Exec, T)>>) -> Work<T>

Function digest

fn digest<T: Encodable<json::Encoder> Decodable<json::Decoder>>(t: &T) -> ~str

Function digest_file

fn digest_file(path: &Path) -> ~str

Function unwrap

fn unwrap<T: Owned Encodable<json::Encoder> Decodable<json::Decoder>>(w:
                                                                          Work<T>)
 -> T