@@ -240,62 +240,69 @@ PS: in writing this section I noticed that cmd has
240
240
241
241
## Variable scope
242
242
243
- Ninja syntactic structures (` build ` , ` rule ` ) are at some level just
244
- lists of key-value bindings that ultimately combine to set properties on
245
- individual build steps, such as the ` command = ... ` command line.
243
+ Ninja syntactic structures (` build ` , ` rule ` ) are at some level just lists of
244
+ key-value bindings that ultimately combine to set properties on individual build
245
+ steps, such as the ` command = ... ` command line.
246
246
247
247
Additionally, bindings can be referenced by other bindings via the ` $foo ` or
248
- ` ${foo} ` syntax. This means variable lookup can recurse through a hierarchy of
249
- scopes. The intent was this was simple enough that the
250
- behavior is straightforward, which in retrospect's insight really just means
251
- "underspecified". (Forgive me! I hacked Ninja together in a few weekends and
252
- made the common mistake of "this is so simple I don't really need to think it
253
- through".)
248
+ ` ${foo} ` syntax. This means variable lookup traverses through a hierarchy of
249
+ scopes. The intent was this was simple enough that the behavior is
250
+ straightforward, which in retrospect's insight really just means
251
+ "underspecified". (Forgive me! I hacked Ninja together in a few weekends and
252
+ made the all too easy mistake of "this is so simple I don't really need to think
253
+ it through".)
254
254
255
- Aside from a conceptual model of the system's rules, ultimately what matters is
256
- what Ninja files in the wild do, which per [ Hyrum's Law] ( https://www.hyrumslaw.com/ )
257
- contain whatever the Ninja implementation allows. However, I don't think it's
258
- really worth fleshing out all the idiosyncracies of Ninja's implementation as long
259
- as existing builds work.
255
+ ### Basics
260
256
261
- Consider the following build file:
257
+ First, here's a high level description that conveys the idea but omits details.
258
+
259
+ Consider a build file like the following:
262
260
263
261
```
264
262
var = $A
265
263
266
264
rule r
267
265
command = $B
268
266
269
- var = $C
270
-
271
- build output-$D: r input-$E
272
- var2 = $F
273
- var2 = $G
267
+ build output-$C: r
268
+ var2 = $D
274
269
```
275
270
276
- These are the scopes to consider, in order of nesting:
277
- 1 . The toplevel scope, the unindented lines marked ` $A ` and ` $C ` .
278
- 1 . The build variable scope, the indented lines in the ` build ` block.
279
- 1 . The build file list scope, the implicit ` $in ` etc. variables.
280
- 1 . The rule scope, the indented lines in the ` rule ` block.
271
+ The ` build ` block stamps out a build step using the rule ` r ` , and the properties
272
+ of that build step are found by looking up attributes like ` command ` .
273
+
274
+ When evaluating the expressions marked ` $A ` / ` $B ` / ` $C ` / ` $D ` above, these are the
275
+ scopes to consider, in order of nesting:
281
276
282
- In summary, lookup for bindings in each can refer to the scopes above them in the
283
- list.
277
+ 1 . The toplevel scope, which defines ` var ` above.
278
+ 1 . The build variable scope, which defines ` var2 ` above.
279
+ 1 . The build file list scope, which defines the implicit ` $in ` etc. variables.
280
+ 1 . The rule scope, which defines ` command ` above.
284
281
285
- Working it through on this example:
282
+ References found in each may refer to the scopes above in the list. For example,
283
+ at the time the ` command = ... ` is evaluated, the in-scope variables include
284
+ ` $in ` , ` $var2 ` , and ` $var ` .
286
285
287
- - Lookup for a toplevel binding (line ` $A ` and ` $C ` ) uses the scope
288
- of toplevel bindings. Consequence: the binding on line ` $C ` can refer
289
- to the first, e.g. if you wrote ` var = ${var}2 ` .
286
+ ### Details
290
287
291
- - Lookup for a build variable (for the value of ` $F ` and ` $G ` ) also only refer
292
- to toplevel bindings. (Lookup for line ` $G ` will not see the binding in line ` $F ` ,
293
- which differs from toplevel, whoops.)
288
+ Unfortunately, [ Hyrum's Law] ( https://www.hyrumslaw.com/ ) means that Ninja files
289
+ in the wild depend on whatever the Ninja implementation allows, which is more
290
+ complex than the above. I don't think it's really worth fleshing out all the
291
+ idiosyncracies of Ninja's implementation as long as existing builds work, but
292
+ some details do matter.
294
293
295
- - Lookup for input/output files ( ` output-$D ` , ` input-$E ` ) refer to build scope
296
- ( the value bound in line ` $G ` , which shadows line ` $F ` ), and then toplevel.
294
+ In particular, Ninja has particular behaviors around variable references found
295
+ within the same scope. Consider:
297
296
298
- - Lookup for rule variables can refer to ` $in ` /` $out ` , build scope, then toplevel.
297
+ ```
298
+ var = 1
299
+ var = ${var}2
300
+ rule ...
301
+ command = echo $depfile
302
+ depfile = abc
303
+ ```
299
304
300
- All the lookups happen when the ` build ` block is visited, which means even
301
- if the ` rule ` block referenced ` var ` it would see the binding from line ` $C ` .
305
+ In Ninja, the value of ` var ` is ` 12 ` : the assignment proceeds from top down. But
306
+ within a ` rule ` block, the variable lookup of ` $depfile ` instead refers forward
307
+ to ` abc ` , which means there is a possibility of circular references, along with
308
+ logic that attempts to detect and warn in those cases(!).
0 commit comments