Selaa lähdekoodia

More documentation.

David Given 7 vuotta sitten
vanhempi
commit
de2f99dc1a
1 muutettua tiedostoa jossa 159 lisäystä ja 9 poistoa
  1. 159 9
      first/ackbuilder.md

+ 159 - 9
first/ackbuilder.md

@@ -1,6 +1,3 @@
-ackbuilder
-==========
-
 # ackbuilder
 
 ## 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.
 
 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
 
@@ -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
 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
 automatically handle library and header paths. The exported headers by the
 library are automatically imported into the program.
@@ -183,17 +189,161 @@ include it:
 
     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",
 	  {
 	     srcs = { type="targets" },
-		 numeric = { type="boolean", default=false }
+		 numeric = { type="boolean", optional=true, default=false }
 	  }
 	  ...omitted...
 
-The most common one is `targets`. When the rule is invoked, ackbuilder will
-resolve these for you so that when your callback fires, the property is a
-flattened list of target objects.
+(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
+	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.