summaryrefslogtreecommitdiffstats
path: root/doc/manual.asciidoc
diff options
context:
space:
mode:
Diffstat (limited to 'doc/manual.asciidoc')
-rw-r--r--doc/manual.asciidoc506
1 files changed, 506 insertions, 0 deletions
diff --git a/doc/manual.asciidoc b/doc/manual.asciidoc
new file mode 100644
index 0000000..7aa000e
--- /dev/null
+++ b/doc/manual.asciidoc
@@ -0,0 +1,506 @@
+Ninja
+=====
+Evan Martin <martine@danga.com>
+
+
+Introduction
+------------
+
+Ninja is yet another build system. It takes as input the
+interdependencies of files (typically source code and output
+executables) and orchestrates building them, _quickly_.
+
+Ninja joins a sea of other build systems. Its distinguishing goal is
+to be fast. It is born from my work on the Chromium browser project,
+which has over 30,000 source files and whose other build systems
+(including one built from custom non-recursive Makefiles) can take ten
+seconds to start building after changing one file. Ninja is under a
+second.
+
+
+Philosophical overview
+~~~~~~~~~~~~~~~~~~~~~~
+
+Build systems get slow when they need to make decisions. When you are
+in a edit-compile cycle you want it to be as fast as possible -- you
+want the build system to do the minimum work necessary to figure out
+what needs to be built immediately.
+
+Ninja contains the barest functionality necessary to describe
+arbitrary dependency graphs. Its lack of syntax makes it impossible
+to express complex decisions. Instead, Ninja is intended to be used
+with a separate program generating its input files. The generator
+program (like the `./configure` found in autotools projects) can
+analyze system dependencies and make as many decisions as possible up
+front so that incremental builds stay fast. Going beyond autotools,
+even build-time decisions like "which compiler flags should I use?"
+or "should I build a debug or release-mode binary?" belong in the
+`.ninja` file generator.
+
+Conceptual overview
+~~~~~~~~~~~~~~~~~~~
+
+Ninja evaluates a graph of dependencies between files, and runs
+whichever commands are necessary to make your build target up to date.
+If you are familiar with Make, Ninja is very similar.
+
+A build file (default name: `build.ninja`) provides a list of _rules_
+-- short names for longer commands, like how to run the compiler --
+along with a list of _build_ statements saying how to build files
+using the rules -- which rule to apply to which inputs to produce
+which outputs.
+
+Conceptually, `build` statements describe the dependency graph of your
+project, while `rule` statements describe how to generate the files
+along a given edge of the graph.
+
+Design goals
+~~~~~~~~~~~~
+
+Here are some of the design goals of Ninja:
+
+* very fast (i.e., instant) incremental builds, even for very large
+ projects.
+
+* very little policy about how code is built; "explicit is better than
+ implicit".
+
+* get dependencies correct, and in particular situations that are
+ difficult to get right with Makefiles (e.g. outputs need an implicit
+ dependency on the command line used to generate them; to build C
+ source code you need to use gcc's `-M` flags for header
+ dependencies).
+
+* when convenience and speed are in conflict, prefer speed.
+
+Some explicit _non-goals_:
+
+* convenient syntax for writing build files by hand. _You should
+ generate your ninja files using another program_. This is how we
+ can sidestep many policy decisions.
+
+* built-in rules. _Out of the box, Ninja has no rules for
+ e.g. compiling C code._
+
+* build-time customization of the build. _Options belong in
+ the program that generates the ninja files_.
+
+* build-time decision-making ability such as conditionals or search
+ paths. _Making decisions is slow._
+
+To restate, Ninja is faster than other build systems because it is
+painfully simple. You must tell Ninja exactly what to do when you
+create your project's `.ninja` files.
+
+Comparison to GNU make
+~~~~~~~~~~~~~~~~~~~~~~
+
+Ninja is closest in spirit and functionality to make. But
+fundamentally, make has a lot of _features_: suffix rules, functions,
+built-in rules that e.g. search for RCS files when building source.
+Many projects find make alone adequate for their build problems. In
+contrast, Ninja has almost no features; just those necessary to get
+builds correct while punting most complexity to generation of the
+ninja input files. Ninja by itself is unlikely to be useful for most
+projects.
+
+Here are some of the features ninja adds to make. (These sorts of
+features can often be implemented using more complicated Makefiles,
+but they are not part of make itself.)
+
+* A Ninja rule may point at a path for extra implicit dependency
+ information. This makes it easy to get header dependencies correct
+ for C/C++ code.
+
+* A build edge may have multiple outputs.
+
+* Outputs implicitly depend on the command line that was used to generate
+ them, which means that changing e.g. compilation flags will cause
+ the outputs to rebuild.
+
+* Output directories are always implicitly created before running the
+ command that relies on them.
+
+* Rules can provide shorter descriptions of the command being run, so
+ you can print e.g. `CC foo.o` instead of a long command line while
+ building.
+
+* Command output is always buffered. This means commands running in
+ parallel don't interleave their output, and when a command fails we
+ can print its failure output next to the full command line that
+ produced the failure.
+
+
+Getting started
+---------------
+
+The included `bootstrap.sh` should hopefully produce a working `ninja`
+binary, by first blindly compiling all non-test files together then
+re-building Ninja using itself.
+
+Usage is currently just
+
+----------------
+ninja target
+----------------
+
+where `target` is a known output described by `build.ninja` in the
+current directory.
+
+There is no installation step; the only files of interest to a user
+are the resulting binary and this manual.
+
+
+Creating .ninja files
+---------------------
+Here's a basic `.ninja` file that demonstrates most of the syntax.
+It will be used as an example for the following sections.
+
+---------------------------------
+cflags = -Wall
+
+rule cc
+ command = gcc $cflags -c $in -o $out
+
+build foo.o: cc foo.c
+---------------------------------
+
+Variables
+~~~~~~~~~
+Despite the non-goal of being convenient to write by hand, to keep
+build files readable (debuggable), Ninja supports declaring shorter
+reusable names for strings. A declaration like the following
+
+----------------
+cflags = -g
+----------------
+
+can be used on the right side of an equals sign, dereferencing it with
+a dollar sign, like this:
+
+----------------
+rule cc
+ command = gcc $cflags -c $in -o $out
+----------------
+
+Variables can also be referenced using curly braces like `${in}`.
+
+Variables might better be called "bindings", in that a given variable
+cannot be changed, only shadowed. There is more on how shadowing works
+later in this document.
+
+Rules
+~~~~~
+
+Rules declare a short name for a command line. They begin with a line
+consisting of the `rule` keyword and a name for the rule. Then
+follows an indented set of `variable = value` lines.
+
+The basic example above declares a new rule named `cc`, along with the
+command to run. (In the context of a rule, the `command` variable is
+special and defines the command to run. A full list of special
+variables is provided in <<ref_rule,the reference>>.)
+
+Within the context of a rule, two additional special variables are
+available: `$in` expands to the list of input files (`foo.c`) and
+`$out` to the output file (`foo.o`) for the command.
+
+
+Build statements
+~~~~~~~~~~~~~~~~
+
+Build statements declare a relationship between input and output
+files. They begin with the `build` keyword, and have the format
++build _outputs_: _rulename_ _inputs_+. Such a declaration says that
+all of the output files are derived from the input files. When the
+output files are missing or when the inputs change, Ninja will run the
+rule to regenerate the outputs.
+
+The basic example above describes how to build `foo.o`, using the `cc`
+rule.
+
+In the scope of a `build` block (including in the evaluation of its
+associated `rule`), the variable `$in` is the list of inputs and the
+variable `$out` is the list of outputs.
+
+A build statement may be followed by an indented set of `key = value`
+pairs, much like a rule. These variables will shadow any variables
+when evaluating the variables in the command. For example:
+
+----------------
+cflags = -Wall -Werror
+rule cc
+ command = gcc $cflags -c $in -o $out
+
+# If left unspecified, builds get the outer $cflags.
+build foo.o: cc foo.c
+
+# But you can can shadow variables like cflags for a particular build.
+build special.o: cc special.c
+ cflags = -Wall
+
+# The variable was only shadowed for the scope of special.o;
+# Subsequent build lines get the outer (original) cflags.
+build bar.o: cc bar.c
+
+----------------
+
+For more discussion of how scoping works, consult <<ref_scope,the
+reference>>.
+
+If you need more complicated information passed from the build
+statement to the rule (for example, if the rule needs "the file
+extension of the first input"), pass that through as an extra
+variable, like how `cflags` is passed above.
+
+
+The `phony` rule
+~~~~~~~~~~~~~~~~
+
+The special rule name `phony` can be used to create aliases for other
+targets. For example:
+
+----------------
+build all: phony some/file/in/a/faraway/subdir
+----------------
+
+This makes `ninja all` build the other files. Semantically, the
+`phony` rule is equivalent to a plain rule where the `command` does
+nothing, but phony rules are handled specially in that they aren't
+printed when run, logged (see below), nor do they contribute to the
+command count printed as part of the build process.
+
+
+The Ninja log
+~~~~~~~~~~~~~
+
+For each built file, Ninja keeps a log of the command used to build
+it. Using this log Ninja can know when an existing output was built
+with a different command line than the build files specify (i.e., the
+command line changed) and knows to rebuild the file.
+
+The log file is kept in the build root in a file called `.ninja_log`.
+If you provide a variable named `builddir` in the outermost scope,
+`.ninja_log` will be kept in that directory instead.
+
+
+Generating Ninja files
+----------------------
+
+A work-in-progress patch to http://gyp.googlecode.com[gyp, the system
+used to generate build files for the Chromium browser] to generate
+ninja files for Linux is included in the source distribution.
+
+Conceptually, you could coax Automake into producing ninja files as
+well, but I haven't tried it. It may very well be the case that most
+projects use too much Makefile syntax in their `.am` files for this to
+work.
+
+Extra tools
+-----------
+
+The `-t` flag on the Ninja command line runs some tools that I have
+found useful during Ninja's development. The current tools are:
+
+`query`:: dump the inputs and outputs of a given target.
+
+`browse`:: browse the dependency graph in a web browser. Clicking a
+file focuses the view on that file, showing inputs and outputs. This
+feature requires a Python installation.
+
+`graph`:: output a file in the syntax used by `graphviz`, a automatic
+graph layout tool. Use it like: +ninja -t graph _target_ | dot -Tpng
+-ograph.png /dev/stdin+ . In the Ninja source tree, `ninja graph`
+generates an image for Ninja itself. If no target is given generate a
+graph for all root targets.
+
+`targets`:: output a list of targets either by rule or by depth. If used
+like this +ninja -t targets rule _name_+ it prints the list of targets
+using the given rule to be built. If no rule is given, it prints the source
+files (the leaves of the graph). If used like this
++ninja -t targets depth _digit_+ it
+prints the list of targets in a depth-first manner starting by the root
+targets (the ones with no outputs). Indentation is used to mark dependencies.
+If the depth is zero it prints all targets. If no arguments are provided
++ninja -t targets depth 1+ is assumed. In this mode targets may be listed
+several times. If used like this +ninja -t targets all+ it
+prints all the targets available without indentation and it is way faster
+than the _depth_ mode. It returns non-zero if an error occurs.
+
+`rules`:: output the list of all rules with their description if they have
+one. It can be used to know which rule name to pass to
++ninja -t targets rule _name_+.
+
+`clean`:: remove built files. If used like this +ninja -t clean+ it
+removes all the built files. If used like this
++ninja -t clean _targets..._+ or like this
++ninja -t clean target _targets..._+ it removes the given targets and
+recursively all files built for it. If used like this
++ninja -t clean rule _rules_+ it removes all files built using the given
+rules. The depfiles are not removed. Files created but not referenced in
+the graph are not removed. This tool takes in account the +-v+ and the
++-n+ options (note that +-n+ implies +-v+). It returns non-zero if an
+error occurs.
+
+Ninja file reference
+--------------------
+
+A file is a series of declarations. A declaration can be one of:
+
+1. A rule declaration, which begins with +rule _rulename_+, and
+ then has a series of indented lines defining variables.
+
+2. A build edge, which looks like +build _output1_ _output2_:
+ _rulename_ _input1_ _input2_+. +
+ Implicit dependencies may be tacked on the end with +|
+ _dependency1_ _dependency2_+. +
+ Order-only dependencies may be tacked on the end with +||
+ _dependency1_ _dependency2_+. (See <<ref_dependencies,the reference on
+ dependency types>>.)
+
+
+3. Variable declarations, which look like +_variable_ = _value_+.
+
+4. References to more files, which look like +subninja _path_+ or
+ +include _path_+. The difference between these is explained below
+ <<ref_scope,in the discussion about scoping>>.
+
+Comments begin with `#` and extend to the end of the line.
+
+Newlines are significant, but they can be escaped by putting a `\`
+before them.
+
+Other whitespace is only significant if it's at the beginning of a
+line. If a line is intended more than the previous one, it's
+considered part of its parent's scope; if it is indented less than the
+previous one, it closes the previous scope.
+
+Rule variables
+~~~~~~~~~~~~~~
+[[ref_rule]]
+
+A `rule` block contains a list of `key = value` declarations that
+affect the processing of the rule. Here is a full list of special
+keys.
+
+`command` (_required_):: the command line to run. This string (after
+ $variables are expanded) is passed directly to `sh -c` without
+ interpretation by Ninja.
+
+`depfile`:: path to an optional `Makefile` that contains extra
+ _implicit dependencies_ (see <<ref_dependencies,the reference on
+ dependency types>>). This is explicitly to support `gcc` and its `-M`
+ family of flags, which output the list of headers a given `.c` file
+ depends on.
++
+Use it like in the following example:
++
+----
+rule cc
+ depfile = $out.d
+ command = gcc -MMD -MF $out.d [other gcc flags here]
+----
++
+When loading a `depfile`, Ninja implicitly adds edges such that it is
+not an error if the listed dependency is missing. This allows you to
+delete a depfile-discovered header file and rebuild, without the build
+aborting due to a missing input.
+
+
+`description`:: a short description of the command, used to pretty-print
+ the command as it's running. The `-v` flag controls whether to print
+ the full command or its description; if a command fails, the full command
+ line will always be printed before the command's output.
+
+Additionally, the special `$in` and `$out` variables expand to the
+space-separated list of files provided to the `build` line referencing
+this `rule`.
+
+Build dependencies
+~~~~~~~~~~~~~~~~~~
+[[ref_dependencies]]
+
+There are three types of build dependencies which are subtly different.
+
+1. _Explicit dependencies_, as listed in a build line. These are
+ available as the `$in` variable in the rule. Changes in these files
+ cause the output to be rebuilt; if these file are missing and
+ Ninja doesn't know how to build them, the build is aborted.
++
+This is the standard form of dependency to be used for e.g. the
+source file of a compile command.
+
+2. _Implicit dependencies_, either as picked up from
+ a `depfile` attribute on a rule or from the syntax +| _dep1_
+ _dep2_+ on the end of a build line. The semantics are identical to
+ explicit dependencies, the only difference is that implicit dependencies
+ don't show up in the `$in` variable.
++
+This is for expressing dependencies that don't show up on the
+command line of the command; for example, for a rule that runs a
+script, the script itself should be an implicit dependency, as
+changes to the script should cause the output to rebuild.
++
+Note that dependencies as loaded through depfiles have slightly different
+semantics, as described in the <<ref_rule,rule reference>>.
+
+3. _Order-only dependencies_, expressed with the syntax +|| _dep1_
+ _dep2_+ on the end of a build line. When these are missing, the
+ output is not rebuilt until they are built, but once they are
+ available further changes to the files do not affect the output.
++
+Order-only dependencies can be useful for bootstrapping dependencies
+that are only discovered during build time: for example, to generate a
+header file before starting a subsequent compilation step. (Once the
+header is used in compilation, a generated dependency file will then
+express the implicit dependency.)
+
+Evaluation and scoping
+~~~~~~~~~~~~~~~~~~~~~~
+[[ref_scope]]
+
+Top-level variable declarations are scoped to the file they occur in.
+
+The `subninja` keyword, used to include another `.ninja` file,
+introduces a new scope. The included `subninja` file may use the
+variables from the parent file, and shadow their values for the file's
+scope, but it won't affect values of the variables in the parent.
+
+To include another `.ninja` file in the current scope, much like a C
+`#include` statement, use `include` instead of `subninja`.
+
+Variable declarations indented in a `build` block are scoped to the
+`build` block. This scope is inherited by the `rule`. The full
+lookup order for a variable referenced in a rule is:
+
+1. Rule-level variables (i.e. `$in`, `$command`).
+
+2. Build-level variables from the `build` that references this rule.
+
+3. File-level variables from the file that the `build` line was in.
+
+4. Variables from the file that included that file using the
+ `subninja` keyword.
+
+Future work
+-----------
+
+Some pieces I'd like to add:
+
+_inotify_. I had originally intended to make Ninja be memory-resident
+and to use `inotify` to keep the build state hot at all times. But
+upon writing the code I found it was fast enough to run from scratch
+each time. Perhaps a slower computer would still benefit from
+inotify; the data structures are set up such that using inotify
+shouldn't be hard.
+
+_build estimation and analysis_. As part of build correctness, Ninja
+keeps a log of the time spent on each build statement. This log
+format could be adjusted to instead store timing information across
+multiple runs. From that, the total time necessary to build could be
+estimated, allowing Ninja to print status like "3 minutes until
+complete" when building. Additionally, a tool could output which
+commands are the slowest or which directories take the most time
+to build.
+
+_many others_. See the `todo` file included in the distribution.