| 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 |
| http://neugierig.org/software/chromium/notes/2011/02/ninja.html[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 |
| ~~~~~~~~~~~~~~~~~~~~~~ |
| |
| Where other build systems are high-level languages, Ninja aims to be |
| an assembler. |
| |
| 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. |
| |
| Design goals |
| ~~~~~~~~~~~~ |
| |
| Here are 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. Different projects and |
| higher-level build systems have different opinions about how code |
| should be built; for example, should built objects live alongside |
| the sources or should all build output go into a separate directory? |
| Is there an "package" rule that builds a distributable package of |
| the project? Sidestep these decisions by trying to allow either to |
| be implemented, rather than choosing, even if that results in |
| more verbosity. |
| |
| * 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 Make |
| ~~~~~~~~~~~~~~~~~~ |
| |
| Ninja is closest in spirit and functionality to make, relying on |
| simple dependencies between file timestamps. |
| |
| But fundamentally, make has a lot of _features_: suffix rules, |
| functions, built-in rules that e.g. search for RCS files when building |
| source. Make's language was designed to be written by humans. 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. |
| |
| * Builds are always run in parallel, based by defaulton the number of |
| CPUs your system has. Underspecified build dependencies will result |
| in incorrect builds. |
| |
| * 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. |
| |
| |
| Using Ninja for your project |
| ---------------------------- |
| |
| Ninja currently works on Unix-like systems. It's seen the most testing |
| on Linux (and has the best performance there) but it runs fine on Mac |
| OS X and FreeBSD. Ninja has some preliminary Windows support but the |
| full details of the implementation -- like how to get C header |
| interdependencies correct and fast when using MSVC's compiler -- is |
| not yet complete. |
| |
| If your project is small, Ninja's speed impact is likely unnoticable. |
| Some build timing numbers are included below. (However, even for |
| small projects it sometimes turns out that Ninja's limited syntax |
| forces simpler build rules that result in faster builds.) Another way |
| to say this is that if you're happy with the edit-compile cycle time |
| of your project already then Ninja won't help. |
| |
| There are many other build systems that are more user-friendly or |
| featureful than Ninja itself. For some recomendations: the Ninja |
| author found http://gittup.org/tup/[the tup build system] influential |
| in Ninja's design, and thinks https://github.com/apenwarr/redo[redo]'s |
| design is quite clever. |
| |
| Ninja's benefit comes from using it in conjunction with a smarter |
| meta-build system. |
| |
| http://code.google.com/p/gyp/[gyp]:: The meta-build system used to |
| generate build files for Google Chrome. gyp can generate Ninja files |
| for Linux and Mac and is used by many Chrome developers; support for |
| Windows is in progress. See the |
| http://code.google.com/p/chromium/wiki/NinjaBuild[Chromium Ninja |
| documentation for more details]. gyp is relatively unpopular outside |
| of the Chrome and v8 world. |
| |
| * For Chrome (~30k source files), Ninja reduced no-op builds from |
| around 15 seconds to under one second. |
| * https://plus.google.com/108996039294665965197/posts/SfhrFAhRyyd[A |
| Mozilla developer compares build systems]: "While chromium's full |
| build is 2.15x slower than firefox's, a nop build is 78.2x faster! |
| That is really noticeable during development. No incremental build |
| of firefox can be faster than 57.9s, which means that in practice |
| almost all of them will be over a minute." |
| |
| http://www.cmake.org/[CMake]:: A widely used meta-build system that |
| can generate Ninja files on Linux as of CMake version 2.8.8. (There |
| is some Mac and Windows support -- http://www.reactos.org[ReactOS] |
| uses Ninja on Windows for their buildbots, but those platforms are not |
| yet officially supported by CMake as the full test suite doesn't |
| pass.) |
| |
| * For building Blender, one user reported "Single file rebuild is 0.97 |
| sec, same on makefiles was 3.7sec." |
| * For building LLVM on Windows, one user reported no-op build times: |
| "ninja: 0.4s / MSBuild: 11s / jom: 53s". |
| |
| others:: Ninja ought to fit perfectly into other meta-build software |
| like http://industriousone.com/premake[premake]. If you do this work, |
| please let us know! |
| |
| Running Ninja |
| ~~~~~~~~~~~~~ |
| |
| Run `ninja`. By default, it looks for a file named `build.ninja` in |
| the current directory and builds all out-of-date targets. You can |
| specify which targets (files) to build as command line arguments. |
| |
| `ninja -h` prints help output. Many of Ninja's flags intentionally |
| match those of Make; e.g `ninja -C build -j 20` changes into the |
| `build` directory and runs 20 build commands in parallel. (Note that |
| Ninja defaults to running commands in parallel anyway, so typically |
| you don't need to pass `-j`.) |
| |
| |
| Environment variables |
| ~~~~~~~~~~~~~~~~~~~~~ |
| |
| Ninja supports one environment variable to control its behavior. |
| |
| `NINJA_STATUS`:: The progress status printed before the rule being run. |
| Several placeholders are available: |
| * `%s`: The number of started edges. |
| * `%t`: The total number of edges that must be run to complete the build. |
| * `%r`: The number of currently running edges. |
| * `%u`: The number of remaining edges to start. |
| * `%f`: The number of finished edges. |
| * `%%`: A plain `%` character. |
| * The default progress status is `"[%s/%t] "` (note the trailing space |
| to separate from the build rule). Another example of possible progress status |
| could be `"[%u/%r/%f] "`. |
| |
| Extra tools |
| ~~~~~~~~~~~ |
| |
| The `-t` flag on the Ninja command line runs some tools that we have |
| found useful during Ninja's development. The current tools are: |
| |
| [horizontal] |
| `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 mytarget | dot -Tpng -ograph.png |
| ---- |
| + |
| In the Ninja source tree, `ninja graph.png` |
| 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 +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 |
| +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 faster |
| than the _depth_ mode. |
| |
| `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_+. |
| |
| `commands`:: given a list of targets, print a list of commands which, if |
| executed in order, may be used to rebuild those targets, assuming that all |
| output files are out of date. |
| |
| `clean`:: remove built files. By default it removes all built files |
| except for those created by the generator. Adding the `-g` flag also |
| removes built files created by the generator (see <<ref_rule,the rule |
| reference for the +generator+ attribute>>). Additional arguments are |
| targets, which removes the given targets and recursively all files |
| built for them. |
| + |
| If used like +ninja -t clean -r _rules_+ it removes all files built using |
| the given rules. |
| + |
| 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+). |
| |
| |
| |
| Writing your own Ninja files |
| ---------------------------- |
| |
| The remainder of this manual is only useful if you are constructing |
| Ninja files yourself: for example, if you're writing a meta-build |
| system or supporting a new language. |
| |
| 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. |
| |
| Syntax example |
| ~~~~~~~~~~~~~~ |
| |
| 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. |
| |
| If the top-level Ninja file is specified as an output of any build |
| statement and it is out of date, Ninja will rebuild and reload it |
| before building the targets requested by the user. |
| |
| |
| Generating Ninja files from code |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| `misc/ninja_syntax.py` in the Ninja distribution is a tiny Python |
| module to facilitate generating Ninja files. It allows you to make |
| Python calls like `ninja.rule(name='foo', command='bar', |
| depfile='$out.d')` and it will generate the appropriate syntax. Feel |
| free to just inline it into your project's build system if it's |
| useful. |
| |
| |
| More details |
| ------------ |
| |
| The `phony` rule |
| ~~~~~~~~~~~~~~~~ |
| |
| The special rule name `phony` can be used to create aliases for other |
| targets. For example: |
| |
| ---------------- |
| build foo: phony some/file/in/a/faraway/subdir/foo |
| ---------------- |
| |
| This makes `ninja foo` build the longer path. 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. |
| |
| `phony` can also be used to create dummy targets for files which |
| may not exist at build time. If a phony build statement is written |
| without any dependencies, the target will be considered out of date if |
| it does not exist. Without a phony build statement, Ninja will report |
| an error if the file does not exist and is required by the build. |
| |
| |
| Default target statements |
| ~~~~~~~~~~~~~~~~~~~~~~~~~ |
| |
| By default, if no targets are specified on the command line, Ninja |
| will build every output that is not named as an input elsewhere. |
| You can override this behavior using a default target statement. |
| A default target statement causes Ninja to build only a given subset |
| of output files if none are specified on the command line. |
| |
| Default target statements begin with the `default` keyword, and have |
| the format +default _targets_+. A default target statement must appear |
| after the build statement that declares the target as an output file. |
| They are cumulative, so multiple statements may be used to extend |
| the list of default targets. For example: |
| |
| ---------------- |
| default foo bar |
| default baz |
| ---------------- |
| |
| This causes Ninja to build the `foo`, `bar` and `baz` targets by |
| default. |
| |
| |
| 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. |
| |
| |
| 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. Default target statements, which look like +default _target1_ _target2_+. |
| |
| 5. 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>>. |
| |
| Lexical syntax |
| ~~~~~~~~~~~~~~ |
| |
| Ninja is mostly encoding agnostic, as long as the bytes Ninja cares |
| about (like slashes in paths) are ASCII. This means e.g. UTF-8 or |
| ISO-8859-1 input files ought to work. |
| |
| Comments begin with `#` and extend to the end of the line. |
| |
| Newlines are significant. Statements like `build foo bar` are a set |
| of space-separated tokens that end at the newline. Newlines and |
| spaces within a token must be escaped. |
| |
| There is only one escape character, `$`, and it has the following |
| behaviors: |
| |
| [horizontal] |
| `$` followed by a newline:: escape the newline (continue the current line |
| across a line break). |
| |
| `$` followed by text:: a variable reference. |
| |
| `${varname}`:: alternate syntax for `$varname`. |
| |
| `$` followed by space:: a space. (This is only necessary in lists of |
| paths, where a space would otherwise separate filenames. See below.) |
| |
| `$:` :: a colon. (This is only necessary in `build` lines, where a colon |
| would otherwise terminate the list of inputs.) |
| |
| `$$`:: a literal `$`. |
| |
| A `build` or `default` statement is first parsed as a space-separated |
| list of filenames and then each name is expanded. This means that |
| spaces within a variable will result in spaces in the expanded |
| filename. |
| |
| ---- |
| spaced = foo bar |
| build $spaced/baz other$ file: ... |
| # The above build line has two outputs: "foo bar/baz" and "other file". |
| ---- |
| |
| In a `name = value` statement, whitespace at the beginning of a value |
| is always stripped. Whitespace at the beginning of a line after a |
| line continuation is also stripped. |
| |
| ---- |
| two_words_with_one_space = foo $ |
| bar |
| one_word_with_no_space = foo$ |
| bar |
| ---- |
| |
| Other whitespace is only significant if it's at the beginning of a |
| line. If a line is indented 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. Each `rule` may have only one `command` |
| declaration. To specify multiple commands use `&&` (or similar) to |
| concatenate operations. |
| |
| `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. |
| |
| `generator`:: if present, specifies that this rule is used to |
| re-invoke the generator program. Files built using `generator` |
| rules are treated specially in two ways: firstly, they will not be |
| rebuilt if the command line changes; and secondly, they are not |
| cleaned by default. |
| |
| `restat`:: if present, causes Ninja to re-stat the command's outputs |
| after execution of the command. Each output whose modification time |
| the command did not change will be treated as though it had never |
| needed to be built. This may cause the output's reverse |
| dependencies to be removed from the list of pending build actions. |
| |
| `rspfile`, `rspfile_content`:: if present (both), Ninja will use a |
| response file for the given command, i.e. write the selected string |
| (`rspfile_content`) to the given file (`rspfile`) before calling the |
| command and delete the file after successful execution of the |
| command. |
| + |
| This is particularly useful on Windows OS, where the maximal length of |
| a command line is limited and response files must be used instead. |
| + |
| Use it like in the following example: |
| + |
| ---- |
| rule link |
| command = link.exe /OUT$out [usual link flags here] @$out.rsp |
| rspfile = $out.rsp |
| rspfile_content = $in |
| |
| build myapp.exe: link a.obj b.obj [possibly many other .obj files] |
| ---- |
| |
| Finally, the special `$in` and `$out` variables expand to the |
| shell-quoted 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 out of date, the |
| output is not rebuilt until they are built, but changes in order-only |
| dependencies alone do not cause the output to be rebuilt. |
| + |
| 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. |
| |
| Variable expansion |
| ~~~~~~~~~~~~~~~~~~ |
| |
| Variables are expanded in paths (in a `build` or `default` statement) |
| and on the right side of a `name = value` statement. |
| |
| When a `name = value` statement is evaluated, its right-hand side is |
| expanded once (according to the above scoping rules) immediately, and |
| from then on `$name` expands to the static string as the result of the |
| expansion. It is never the case that you'll need to "double-escape" a |
| value to prevent it from getting expanded twice. |