More documentation.
This commit is contained in:
parent
ea4142daee
commit
de2f99dc1a
|
@ -1,6 +1,3 @@
|
||||||
ackbuilder
|
|
||||||
==========
|
|
||||||
|
|
||||||
# ackbuilder
|
# ackbuilder
|
||||||
|
|
||||||
## What is it?
|
## What is it?
|
||||||
|
@ -13,7 +10,12 @@ hopefully-robust support for rules which generate more than one output file,
|
||||||
which is something make is very, very bad at.
|
which is something make is very, very bad at.
|
||||||
|
|
||||||
It was written because the ACK is a really horribly complex thing to build and
|
It was written because the ACK is a really horribly complex thing to build and
|
||||||
there wasn't anything else.
|
there wasn't anything else. ackbuilder is pretty rough and ready but it does
|
||||||
|
sort of work. Be prepared for bugs.
|
||||||
|
|
||||||
|
This document is a very rapid brain dump of how the build file works. It
|
||||||
|
doesn't cover actually running the tool (because that bit's pretty nasty) ---
|
||||||
|
go look at the top level Makefile to see that for now.
|
||||||
|
|
||||||
## Basic concepts
|
## Basic concepts
|
||||||
|
|
||||||
|
@ -67,6 +69,10 @@ interpreted then and there. You can't have circular dependencies (these are
|
||||||
caught and an error is generated). You can't refer to a target defined below
|
caught and an error is generated). You can't refer to a target defined below
|
||||||
you in the same source file (these are not caught, and just won't be found).
|
you in the same source file (these are not caught, and just won't be found).
|
||||||
|
|
||||||
|
Build files each get their own private global scope. If you randomly set a
|
||||||
|
variable, it won't be seen by other build files. (Use `vars` for that; see
|
||||||
|
below.) Build files are only loaded once.
|
||||||
|
|
||||||
The `cprogram` and `clibrary` rules, by the way, are sophisticated enough to
|
The `cprogram` and `clibrary` rules, by the way, are sophisticated enough to
|
||||||
automatically handle library and header paths. The exported headers by the
|
automatically handle library and header paths. The exported headers by the
|
||||||
library are automatically imported into the program.
|
library are automatically imported into the program.
|
||||||
|
@ -183,17 +189,161 @@ include it:
|
||||||
|
|
||||||
include("foo/bar/baz/build.lua")
|
include("foo/bar/baz/build.lua")
|
||||||
|
|
||||||
Rule properties are typed and can be specified to be required or optional (or have a default value).
|
Rule properties are typed and can be specified to be required or optional (or
|
||||||
|
have a default value). If you try to invoke a rule with a property which isn't
|
||||||
|
declared, or missing a property which should be declared, you'll get an error.
|
||||||
|
|
||||||
definerule("sort",
|
definerule("sort",
|
||||||
{
|
{
|
||||||
srcs = { type="targets" },
|
srcs = { type="targets" },
|
||||||
numeric = { type="boolean", default=false }
|
numeric = { type="boolean", optional=true, default=false }
|
||||||
}
|
}
|
||||||
...omitted...
|
...omitted...
|
||||||
|
|
||||||
The most common one is `targets`. When the rule is invoked, ackbuilder will
|
(The `optional=true` part can be omitted if you specify a default which isn't
|
||||||
|
`nil`.)
|
||||||
|
|
||||||
|
Types include:
|
||||||
|
|
||||||
|
* `targets`: the most common one. When the rule is invoked, ackbuilder will
|
||||||
resolve these for you so that when your callback fires, the property is a
|
resolve these for you so that when your callback fires, the property is a
|
||||||
flattened list of target objects.
|
flattened list of target objects.
|
||||||
|
|
||||||
|
* `strings`: a Lua table of strings. If the invoker supplies a single string
|
||||||
|
which isn't a table, it'll get wrapped in one.
|
||||||
|
|
||||||
|
* `string`: a string.
|
||||||
|
|
||||||
|
* `boolean`: a boolean (either `true` or `false`; nothing else is allowed).
|
||||||
|
|
||||||
|
* `table`: a Lua table.
|
||||||
|
|
||||||
|
* `object`: any Lua value.
|
||||||
|
|
||||||
|
## Target objects
|
||||||
|
|
||||||
|
When a rule callback is run, any targets it needs will be resolved into target
|
||||||
|
objects. These are Lua objects with assorted useful stuff in them.
|
||||||
|
|
||||||
|
* `object.is`: contains a set telling you which rules made the object. e.g.
|
||||||
|
`object.is.cprogram` is true if `object` was built with `cprogram`. Bear in
|
||||||
|
mind that `object.is.normalrule` is _also_ going to be true.
|
||||||
|
|
||||||
|
* `object.dir`: the object's build directory. Only exists if the object was
|
||||||
|
built with `normalrule`.
|
||||||
|
|
||||||
|
There are other properties (`fullname` and `outs`). Please don't use these; use
|
||||||
|
`targetnamesof()` and `filenamesof()` as described below.
|
||||||
|
|
||||||
|
## The standard library
|
||||||
|
|
||||||
|
Your build files are supplied a pile of useful functions.
|
||||||
|
|
||||||
|
### Manipulating target lists
|
||||||
|
|
||||||
|
A target list is a possibly nested set of tables containing either target
|
||||||
|
objects or strings. All of these functions will implicitly flatten the list and
|
||||||
|
resolve any strings into target objects before doing anything else to them.
|
||||||
|
Most of these functions can be supplied with varargs parameters.
|
||||||
|
|
||||||
|
e.g. `targetsof(a, b)` is equivalent to `targetsof({a, b})` is equivalent to
|
||||||
|
`targetsof({a, {b}})`.
|
||||||
|
|
||||||
|
* `targetsof(...)`: just flattens the list and resolves any string target
|
||||||
|
names.
|
||||||
|
|
||||||
|
* `filenamesof(...)`: returns a list of output files for all the supplied
|
||||||
|
targets.
|
||||||
|
|
||||||
|
* `targetnamesof(...)`: returns a list of fully qualified target names for
|
||||||
|
all the supplied stargets.
|
||||||
|
|
||||||
|
* `selectof(targets, pattern)`: returns only those targets whose outputs
|
||||||
|
contain at least one file matching the pattern.
|
||||||
|
|
||||||
|
### Manipulating filename lists
|
||||||
|
|
||||||
|
Like the target list functions, all of these implicitly flatten any nested
|
||||||
|
tables. They all return lists; however, as a special exception, if any of the
|
||||||
|
functions which take varargs parameters have a single parameter which is a
|
||||||
|
string, they return just a string.
|
||||||
|
|
||||||
|
e.g. `abspath({f})` returns a table; `abspath(f)` returns a string.
|
||||||
|
|
||||||
|
* `abspath(...)`: attempts to return the absolute path of its arguments. This
|
||||||
|
isn't always possible due to variable references.
|
||||||
|
|
||||||
|
* `basename(...)`: returns the basenames of its arguments (the file part of
|
||||||
|
the path).
|
||||||
|
|
||||||
|
* `dirname(...)`: returns the directory name of its arguments.
|
||||||
|
|
||||||
|
* `matching(files, pattern)`: returns only those files which match a Lua
|
||||||
|
pattern.
|
||||||
|
|
||||||
|
* `replace(files, pattern, repl)`: performs a Lua pattern replace on the list
|
||||||
|
of files.
|
||||||
|
|
||||||
|
* `uniquify(...)`: removes duplicates.
|
||||||
|
|
||||||
|
### Other things
|
||||||
|
|
||||||
|
* `include(file)`: loads another build file, if it hasn't been loaded before.
|
||||||
|
|
||||||
|
## Variables
|
||||||
|
|
||||||
|
There are two types of variable, mostly for hysterical reasons.
|
||||||
|
|
||||||
|
### Makefile variables
|
||||||
|
|
||||||
|
(Despite the name, these work on ninja too.)
|
||||||
|
|
||||||
|
Filenames can contain variable references of the form `$(FOO)`. These are
|
||||||
|
expanded at build time based on definitions supplied on the ackbuilder command
|
||||||
|
line.
|
||||||
|
|
||||||
|
ackbuilder assumes that these are absolute paths and won't attempt to
|
||||||
|
manipulate them much.
|
||||||
|
|
||||||
|
I want to get rid of these at some point.
|
||||||
|
|
||||||
|
### ackbuilder variables
|
||||||
|
|
||||||
|
These are expanded by ackbuilder itself.
|
||||||
|
|
||||||
|
Every rule invocation contains a magic property, `vars`. When a rule's commands
|
||||||
|
are executed, the variables provided in the template expansion are calculated
|
||||||
|
by combining all `vars` settings in the call stack (including the top level
|
||||||
|
build file).
|
||||||
|
|
||||||
|
Easiest to explain with an example:
|
||||||
|
|
||||||
|
cprogram {
|
||||||
|
name = 'another_test',
|
||||||
|
srcs = { './*.c' },
|
||||||
|
vars = {
|
||||||
|
cflags = { '-g', '-O3' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
When `cprogram` builds each C file, the command will refer to `%{cflags}`. The
|
||||||
|
value above will be flattened into a space-separated string and substituted in.
|
||||||
|
|
||||||
|
Setting a variable this way will _override_ any definition further up the call
|
||||||
|
stack. However, you can do this:
|
||||||
|
|
||||||
|
vars.cflags = { '-g' }
|
||||||
|
|
||||||
|
cprogram {
|
||||||
|
name = 'another_test',
|
||||||
|
srcs = { './*.c' },
|
||||||
|
vars = {
|
||||||
|
["+cflags"] = { '-O3' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Now `cflags` will default to `-g` everywhere, because it's set at the top
|
||||||
|
level; but when `another_test` is built, it'll be `-g -O3`.
|
||||||
|
|
||||||
|
ackbuilder variables are only expanded in command templates, not in filenames.
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue