Parcourir la source

More documentation.

David Given il y a 7 ans
Parent
commit
de2f99dc1a
1 fichiers modifiés avec 159 ajouts et 9 suppressions
  1. 159 9
      first/ackbuilder.md

+ 159 - 9
first/ackbuilder.md

@@ -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
-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.