xref: /aosp_15_r20/build/make/tools/canoninja/README.md (revision 9e94795a3d4ef5c1d47486f9a02bb378756cea8a)
1*9e94795aSAndroid Build Coastguard Worker# Ninja File Canonicalizer
2*9e94795aSAndroid Build Coastguard Worker
3*9e94795aSAndroid Build Coastguard WorkerSuppose we have a tool that generates a Ninja file from some other description (think Kati and makefiles), and during
4*9e94795aSAndroid Build Coastguard Workerthe testing we discovered a regression. Furthermore, suppose that the generated Ninja file is large (think millions of
5*9e94795aSAndroid Build Coastguard Workerlines). And, the new Ninja file has build statements and rules in a slightly different order. As the tool generates the
6*9e94795aSAndroid Build Coastguard Workerrule names, the real differences in the output of the `diff` command are drowned in noise. Enter Canoninja.
7*9e94795aSAndroid Build Coastguard Worker
8*9e94795aSAndroid Build Coastguard WorkerCanoninja renames each Ninja rule to the hash of its contents. After that, we can just sort the build statements, and a
9*9e94795aSAndroid Build Coastguard Workersimple `comm` command immediately reveal the essential difference between the files.
10*9e94795aSAndroid Build Coastguard Worker
11*9e94795aSAndroid Build Coastguard Worker## Example
12*9e94795aSAndroid Build Coastguard Worker
13*9e94795aSAndroid Build Coastguard WorkerConsider the following makefile
14*9e94795aSAndroid Build Coastguard Worker
15*9e94795aSAndroid Build Coastguard Worker```makefile
16*9e94795aSAndroid Build Coastguard Workersecond :=
17*9e94795aSAndroid Build Coastguard Workerfirst: foo
18*9e94795aSAndroid Build Coastguard Workerfoo:
19*9e94795aSAndroid Build Coastguard Worker	@echo foo
20*9e94795aSAndroid Build Coastguard Workersecond: bar
21*9e94795aSAndroid Build Coastguard Workerbar:
22*9e94795aSAndroid Build Coastguard Worker	@echo bar
23*9e94795aSAndroid Build Coastguard Worker```
24*9e94795aSAndroid Build Coastguard Worker
25*9e94795aSAndroid Build Coastguard WorkerDepending on Kati version converting it to Ninja file will yield either:
26*9e94795aSAndroid Build Coastguard Worker
27*9e94795aSAndroid Build Coastguard Worker```
28*9e94795aSAndroid Build Coastguard Worker$ cat /tmp/1.ninja
29*9e94795aSAndroid Build Coastguard Worker# Generated by kati 06f2569b2d16628608c000a76e3d495a5a5528cb
30*9e94795aSAndroid Build Coastguard Worker
31*9e94795aSAndroid Build Coastguard Workerpool local_pool
32*9e94795aSAndroid Build Coastguard Worker depth = 72
33*9e94795aSAndroid Build Coastguard Worker
34*9e94795aSAndroid Build Coastguard Workerbuild _kati_always_build_: phony
35*9e94795aSAndroid Build Coastguard Worker
36*9e94795aSAndroid Build Coastguard Workerbuild first: phony foo
37*9e94795aSAndroid Build Coastguard Workerrule rule0
38*9e94795aSAndroid Build Coastguard Worker description = build $out
39*9e94795aSAndroid Build Coastguard Worker command = /bin/sh -c "echo foo"
40*9e94795aSAndroid Build Coastguard Workerbuild foo: rule0
41*9e94795aSAndroid Build Coastguard Workerbuild second: phony bar
42*9e94795aSAndroid Build Coastguard Workerrule rule1
43*9e94795aSAndroid Build Coastguard Worker description = build $out
44*9e94795aSAndroid Build Coastguard Worker command = /bin/sh -c "echo bar"
45*9e94795aSAndroid Build Coastguard Workerbuild bar: rule1
46*9e94795aSAndroid Build Coastguard Worker
47*9e94795aSAndroid Build Coastguard Workerdefault first
48*9e94795aSAndroid Build Coastguard Worker```
49*9e94795aSAndroid Build Coastguard Worker
50*9e94795aSAndroid Build Coastguard Workeror
51*9e94795aSAndroid Build Coastguard Worker
52*9e94795aSAndroid Build Coastguard Worker```
53*9e94795aSAndroid Build Coastguard Worker$ cat 2.ninja
54*9e94795aSAndroid Build Coastguard Worker# Generated by kati 371194da71b3e191fea6f2ccceb7b061bd0de310
55*9e94795aSAndroid Build Coastguard Worker
56*9e94795aSAndroid Build Coastguard Workerpool local_pool
57*9e94795aSAndroid Build Coastguard Worker depth = 72
58*9e94795aSAndroid Build Coastguard Worker
59*9e94795aSAndroid Build Coastguard Workerbuild _kati_always_build_: phony
60*9e94795aSAndroid Build Coastguard Worker
61*9e94795aSAndroid Build Coastguard Workerbuild second: phony bar
62*9e94795aSAndroid Build Coastguard Workerrule rule0
63*9e94795aSAndroid Build Coastguard Worker description = build $out
64*9e94795aSAndroid Build Coastguard Worker command = /bin/sh -c "echo bar"
65*9e94795aSAndroid Build Coastguard Workerbuild bar: rule0
66*9e94795aSAndroid Build Coastguard Workerbuild first: phony foo
67*9e94795aSAndroid Build Coastguard Workerrule rule1
68*9e94795aSAndroid Build Coastguard Worker description = build $out
69*9e94795aSAndroid Build Coastguard Worker command = /bin/sh -c "echo foo"
70*9e94795aSAndroid Build Coastguard Workerbuild foo: rule1
71*9e94795aSAndroid Build Coastguard Worker
72*9e94795aSAndroid Build Coastguard Workerdefault first
73*9e94795aSAndroid Build Coastguard Worker```
74*9e94795aSAndroid Build Coastguard Worker
75*9e94795aSAndroid Build Coastguard WorkerThis is a quirk in Kati, see https://github.com/google/kati/issues/238
76*9e94795aSAndroid Build Coastguard Worker
77*9e94795aSAndroid Build Coastguard WorkerTrying to find out the difference between the targets even after sorting them isn't too helpful:
78*9e94795aSAndroid Build Coastguard Worker
79*9e94795aSAndroid Build Coastguard Worker```
80*9e94795aSAndroid Build Coastguard Workerdiff <(grep '^build' /tmp/1.ninja|sort) <(grep '^build' /tmp/2.ninja | sort)
81*9e94795aSAndroid Build Coastguard Worker1c1
82*9e94795aSAndroid Build Coastguard Worker< build bar: rule1
83*9e94795aSAndroid Build Coastguard Worker---
84*9e94795aSAndroid Build Coastguard Worker> build bar: rule0
85*9e94795aSAndroid Build Coastguard Worker3c3
86*9e94795aSAndroid Build Coastguard Worker< build foo: rule0
87*9e94795aSAndroid Build Coastguard Worker---
88*9e94795aSAndroid Build Coastguard Worker> build foo: rule1
89*9e94795aSAndroid Build Coastguard Worker```
90*9e94795aSAndroid Build Coastguard Worker
91*9e94795aSAndroid Build Coastguard WorkerHowever, running these files through `canoninja` yields
92*9e94795aSAndroid Build Coastguard Worker
93*9e94795aSAndroid Build Coastguard Worker```
94*9e94795aSAndroid Build Coastguard Worker$ canoninja /tmp/1.ninja
95*9e94795aSAndroid Build Coastguard Worker# Generated by kati 06f2569b2d16628608c000a76e3d495a5a5528cb
96*9e94795aSAndroid Build Coastguard Worker
97*9e94795aSAndroid Build Coastguard Workerpool local_pool
98*9e94795aSAndroid Build Coastguard Worker depth = 72
99*9e94795aSAndroid Build Coastguard Worker
100*9e94795aSAndroid Build Coastguard Workerbuild _kati_always_build_: phony
101*9e94795aSAndroid Build Coastguard Worker
102*9e94795aSAndroid Build Coastguard Workerbuild first: phony foo
103*9e94795aSAndroid Build Coastguard Workerrule R2f9981d3c152fc255370dc67028244f7bed72a03
104*9e94795aSAndroid Build Coastguard Worker description = build $out
105*9e94795aSAndroid Build Coastguard Worker command = /bin/sh -c "echo foo"
106*9e94795aSAndroid Build Coastguard Workerbuild foo: R2f9981d3c152fc255370dc67028244f7bed72a03
107*9e94795aSAndroid Build Coastguard Workerbuild second: phony bar
108*9e94795aSAndroid Build Coastguard Workerrule R62640f3f9095cf2da5b9d9e2a82f746cc710c94c
109*9e94795aSAndroid Build Coastguard Worker description = build $out
110*9e94795aSAndroid Build Coastguard Worker command = /bin/sh -c "echo bar"
111*9e94795aSAndroid Build Coastguard Workerbuild bar: R62640f3f9095cf2da5b9d9e2a82f746cc710c94c
112*9e94795aSAndroid Build Coastguard Worker
113*9e94795aSAndroid Build Coastguard Workerdefault first
114*9e94795aSAndroid Build Coastguard Worker```
115*9e94795aSAndroid Build Coastguard Worker
116*9e94795aSAndroid Build Coastguard Workerand
117*9e94795aSAndroid Build Coastguard Worker
118*9e94795aSAndroid Build Coastguard Worker```
119*9e94795aSAndroid Build Coastguard Worker~/go/bin/canoninja /tmp/2.ninja
120*9e94795aSAndroid Build Coastguard Worker# Generated by kati 371194da71b3e191fea6f2ccceb7b061bd0de310
121*9e94795aSAndroid Build Coastguard Worker
122*9e94795aSAndroid Build Coastguard Workerpool local_pool
123*9e94795aSAndroid Build Coastguard Worker depth = 72
124*9e94795aSAndroid Build Coastguard Worker
125*9e94795aSAndroid Build Coastguard Workerbuild _kati_always_build_: phony
126*9e94795aSAndroid Build Coastguard Worker
127*9e94795aSAndroid Build Coastguard Workerbuild second: phony bar
128*9e94795aSAndroid Build Coastguard Workerrule R62640f3f9095cf2da5b9d9e2a82f746cc710c94c
129*9e94795aSAndroid Build Coastguard Worker description = build $out
130*9e94795aSAndroid Build Coastguard Worker command = /bin/sh -c "echo bar"
131*9e94795aSAndroid Build Coastguard Workerbuild bar: R62640f3f9095cf2da5b9d9e2a82f746cc710c94c
132*9e94795aSAndroid Build Coastguard Workerbuild first: phony foo
133*9e94795aSAndroid Build Coastguard Workerrule R2f9981d3c152fc255370dc67028244f7bed72a03
134*9e94795aSAndroid Build Coastguard Worker description = build $out
135*9e94795aSAndroid Build Coastguard Worker command = /bin/sh -c "echo foo"
136*9e94795aSAndroid Build Coastguard Workerbuild foo: R2f9981d3c152fc255370dc67028244f7bed72a03
137*9e94795aSAndroid Build Coastguard Worker
138*9e94795aSAndroid Build Coastguard Workerdefault first
139*9e94795aSAndroid Build Coastguard Worker```
140*9e94795aSAndroid Build Coastguard Worker
141*9e94795aSAndroid Build Coastguard Workerand when we extract only build statements and sort them, we see that both Ninja files define the same graph:
142*9e94795aSAndroid Build Coastguard Worker
143*9e94795aSAndroid Build Coastguard Worker```shell
144*9e94795aSAndroid Build Coastguard Worker$ diff <(~/go/bin/canoninja /tmp/1.ninja | grep '^build' | sort) \
145*9e94795aSAndroid Build Coastguard Worker       <(~/go/bin/canoninja /tmp/2.ninja | grep '^build' | sort)
146*9e94795aSAndroid Build Coastguard Worker```
147*9e94795aSAndroid Build Coastguard Worker
148*9e94795aSAndroid Build Coastguard Worker# Todo
149*9e94795aSAndroid Build Coastguard Worker
150*9e94795aSAndroid Build Coastguard Worker* Optionally output only the build statements, optionally sorted
151*9e94795aSAndroid Build Coastguard Worker* Handle continuation lines correctly
152