README.md
1# LLVM Tools
2
3## Overview
4
5These scripts helps automate tasks such as updating the LLVM next hash,
6determing whether a new patch applies correctly, and patch management.
7
8In addition, there are scripts that automate the process of retrieving the
9git hash of LLVM from either google3, top of trunk, or for a specific SVN
10version.
11
12**NOTE: All scripts must must be run outside the chroot**
13
14**NOTE: sudo must be permissive (i.e. **`cros_sdk`** should NOT prompt for a
15password)**
16
17## `update_packages_and_run_tests.py`
18
19### Usage
20
21This script is used for updating a package's LLVM hash (sys-devel/llvm,
22sys-libs/compiler-rt, sys-libs/libcxx, and sys-libs/llvm-libunwind)
23and then run tests after updating the git hash. There are three ways to test
24the change, including starting tryjobs, recipe builders or using cq+1.
25
26An example when this script should be run is when certain boards would like
27to be tested with the updated `LLVM_NEXT_HASH`.
28
29For example:
30
31```
32$ ./update_packages_and_run_tests.py \
33 --is_llvm_next \
34 --llvm_version tot \
35 tryjobs \
36 --options nochromesdk latest-toolchain \
37 --builders kevin-release-tryjob nocturne-release-tryjob
38```
39
40The above example would update the packages' `LLVM_NEXT_HASH` to the top of
41trunk's git hash and would submit tryjobs for kevin and nocturne boards, passing
42in 'nochromesdk' and 'latest-toolchain' for each tryjob.
43
44For help with the command line arguments of the script, run:
45
46```
47$ ./update_packages_and_run_tests.py --help
48```
49
50Similarly as the previous example, but for updating `LLVM_HASH` to
51google3 and test with cq+1:
52
53```
54$ ./update_packages_and_run_tests.py \
55 --llvm_version google3 \
56 cq
57```
58
59Similarly as the previous example, but for updating `LLVM_NEXT_HASH` to
60the git hash of revision 367622 and test with recipe builders:
61
62```
63$ ./update_packages_and_run_tests.py \
64 --is_llvm_next \
65 --llvm_version 367622 \
66 recipe \
67 --options -nocanary \
68 --builders chromeos/toolchain/kevin-llvm chromeos/toolchain/nocturne-llvm
69```
70
71## `update_chromeos_llvm_hash.py`
72
73### Usage
74
75This script is used for updating a package's/packages' LLVM hashes and
76creating a change list of those changes which will uploaded for review. For
77example, some changes that would be included in the change list are
78the updated ebuilds, changes made to the patches of the updated packages such
79as being removed or an updated patch metadata file. These changes are determined
80by the `--failure_mode` option.
81
82An example where this script would be used is when multiple packages need to
83have their `LLVM_NEXT_HASH` updated.
84
85For example:
86
87```
88$ ./update_chromeos_llvm_hash.py \
89 --update_packages sys-devel/llvm sys-libs/compiler-rt \
90 --is_llvm_next \
91 --llvm_version google3 \
92 --failure_mode disable_patches
93```
94
95The example above would update sys-devel/llvm and sys-libs/compiler-rt's
96`LLVM_NEXT_HASH` to the latest google3's git hash of LLVM. And the change list
97may include patches that were disabled for either sys-devel/llvm or
98sys-libs/compiler-rt.
99
100For help with the command line arguments of the script, run:
101
102```
103$ ./update_chromeos_llvm_hash.py --help
104```
105
106For example, to update `LLVM_HASH` to top of trunk of LLVM:
107
108```
109$ ./update_chromeos_llvm_hash.py \
110 --update_packages sys-devel/llvm sys-libs/compiler-rt \
111 --llvm_version tot \
112 --failure_mode disable_patches
113```
114
115For example, to create a roll CL to the git hash of revision 367622:
116
117```
118$ ./update_chromeos_llvm_hash.py \
119 --update_packages sys-devel/llvm sys-libs/compiler-rt \
120 sys-libs/libcxx sys-libs/llvm-libunwind \
121 'dev-util/lldb-server' \
122 --llvm_version 367622 \
123 --failure_mode disable_patches
124```
125
126## `patch_manager.py`
127
128### Usage
129
130This script is used when when all the command line arguments are known such as
131testing a specific metadata file or a specific source tree.
132
133For help with the command line arguments of the script, run:
134
135```
136$ ./patch_manager.py --help
137```
138
139For example, to see all the failed (if any) patches:
140
141```
142$ ./patch_manager.py \
143 --svn_version 367622 \
144 --patch_metadata_file /abs/path/to/patch/file \
145 --src_path /abs/path/to/src/tree \
146 --failure_mode continue
147```
148
149For example, to disable all patches that failed to apply:
150
151```
152$ ./patch_manager.py \
153 --svn_version 367622 \
154 --patch_metadata_file /abs/path/to/patch/file \
155 --src_path /abs/path/to/src/tree \
156 --failure_mode disable_patches
157```
158
159For example, to bisect a failing patch and stop at the first bisected patch:
160
161```
162$ ./patch_manager.py \
163 --svn_version 367622 \
164 --patch_metadata_file /abs/path/to/patch/file \
165 --src_path /abs/path/to/src/tree \
166 --failure_mode bisect_patches \
167 --good_svn_version 365631
168```
169
170For example, to bisect a failing patch and then continue bisecting the rest of
171the failed patches:
172
173```
174$ ./patch_manager.py \
175 --svn_version 367622 \
176 --patch_metadata_file /abs/path/to/patch/file \
177 --src_path /abs/path/to/src/tree \
178 --failure_mode bisect_patches \
179 --good_svn_version 365631 \
180 --continue_bisection True
181```
182
183## LLVM Bisection
184
185### `llvm_bisection.py`
186
187#### Usage
188
189This script is used to bisect a bad revision of LLVM. After the script finishes,
190the user requires to run the script again to continue the bisection. Intially,
191the script creates a JSON file that does not exist which then continues
192bisection (after invoking the script again) based off of the JSON file.
193
194For example, assuming the revision 369420 is the bad revision:
195
196```
197$ ./llvm_bisection.py \
198 --parallel 3 \
199 --start_rev 369410 \
200 --end_rev 369420 \
201 --last_tested /abs/path/to/tryjob/file/ \
202 --extra_change_lists 513590 \
203 --builder eve-release-tryjob \
204 --options latest-toolchain
205```
206
207The above example bisects the bad revision (369420), starting from the good
208revision 369410 and launching 3 tryjobs in between if possible (`--parallel`).
209Here, the `--last_tested` path is a path to a JSON file that does not exist. The
210tryjobs are tested on the eve board. `--extra_change_lists` and `--options`
211indicate what parameters to pass into launching a tryjob.
212
213For help with the command line arguments of the script, run:
214
215```
216$ ./llvm_bisection.py --help
217```
218
219### `auto_llvm_bisection.py`
220
221#### Usage
222
223This script automates the LLVM bisection process by using `cros buildresult` to
224update the status of each tryjob.
225
226An example when this script would be used to do LLVM bisection overnight
227because tryjobs take very long to finish.
228
229For example, assuming the good revision is 369410 and the bad revision is
230369420, then:
231
232```
233$ ./auto_llvm_bisection.py --start_rev 369410 --end_rev 369420 \
234 --last_tested /abs/path/to/last_tested_file.json \
235 --extra_change_lists 513590 1394249 \
236 --options latest-toolchain nochromesdk \
237 --chromeos_path /path/to/chromeos/chroot \
238 --builder eve-release-tryjob
239```
240
241The example above bisects LLVM between revision 369410 and 369420. If the file
242exists, the script resumes bisection. Otherwise, the script creates the file
243provided by `--last_tested`. `--extra_change_lists` and `--options` are used for
244each tryjob when being submitted. Lastly, the tryjobs are launched for the board
245provided by `--builder` (in this example, for the eve board).
246
247For help with the command line arguments of the script, run:
248
249```
250$ ./auto_llvm_bisection.py --help
251```
252
253### `update_tryjob_status.py`
254
255#### Usage
256
257This script updates a tryjob's 'status' value when bisecting LLVM. This script
258can use the file that was created by `llvm_bisection.py`.
259
260An example when this script would be used is when the result of tryjob that was
261launched was 'fail' (due to flaky infra) but it should really have been
262'success'.
263
264For example, to update a tryjob's 'status' to 'good':
265
266```
267$ ./update_tryjob_status.py \
268 --set_status good \
269 --revision 369412 \
270 --status_file /abs/path/to/tryjob/file
271```
272
273The above example uses the file in `--status_file` to update a tryjob in that
274file that tested the revision 369412 and sets its 'status' value to 'good'.
275
276For help with the command line arguments of the script, run:
277
278```
279$ ./update_tryjob_status.py --help
280```
281
282For example, to update a tryjob's 'status' to 'bad':
283
284```
285$ ./update_tryjob_status.py \
286 --set_status bad \
287 --revision 369412 \
288 --status_file /abs/path/to/tryjob/file
289```
290
291For example, to update a tryjob's 'status' to 'pending':
292
293```
294$ ./update_tryjob_status.py \
295 --set_status pending \
296 --revision 369412 \
297 --status_file /abs/path/to/tryjob/file
298```
299
300For example, to update a tryjob's 'status' to 'skip':
301
302```
303$ ./update_tryjob_status.py \
304 --set_status skip \
305 --revision 369412 \
306 --status_file /abs/path/to/tryjob/file
307```
308
309For example, to update a tryjob's 'status' based off a custom script exit code:
310
311```
312$ ./update_tryjob_status.py \
313 --set_status custom_script \
314 --revision 369412 \
315 --status_file /abs/path/to/tryjob/file \
316 --custom_script /abs/path/to/script.py
317```
318
319### `modify_a_tryjob.py`
320
321#### Usage
322
323This script modifies a tryjob directly given an already created tryjob file when
324bisecting LLVM. The file created by `llvm_bisection.py` can be used in this
325script.
326
327An example when this script would be used is when a tryjob needs to be manually
328added.
329
330For example:
331
332```
333$ ./modify_a_tryjob.py \
334 --modify_a_tryjob add \
335 --revision 369416 \
336 --extra_change_lists 513590 \
337 --options latest-toolchain \
338 --builder eve-release-tryjob \
339 --status_file /abs/path/to/tryjob/file
340```
341
342The above example creates a tryjob that tests revision 369416 on the eve board,
343passing in the extra arguments (`--extra_change_lists` and `--options`). The
344tryjob is then inserted into the file passed in via `--status_file`.
345
346For help with the command line arguments of the script, run:
347
348```
349$ ./modify_a_tryjob.py --help
350```
351
352For example, to remove a tryjob that tested revision 369412:
353
354```
355$ ./modify_a_tryjob.py \
356 --modify_a_tryjob remove \
357 --revision 369412 \
358 --status_file /abs/path/to/tryjob/file
359```
360
361For example, to relaunch a tryjob that tested revision 369418:
362
363```
364$ ./modify_a_tryjob.py \
365 --modify_a_tryjob relaunch \
366 --revision 369418 \
367 --status_file /abs/path/to/tryjob/file
368```
369
370## Other Helpful Scripts
371
372### `get_llvm_hash.py`
373
374#### Usage
375
376The script has a class that deals with retrieving either the top of trunk git
377hash of LLVM, the git hash of google3, or a specific git hash of a SVN version.
378It also has other functions when dealing with a git hash of LLVM.
379
380In addition, it has a function to retrieve the latest google3 LLVM version.
381
382For example, to retrieve the top of trunk git hash of LLVM:
383
384```
385from get_llvm_hash import LLVMHash
386
387LLVMHash().GetTopOfTrunkGitHash()
388```
389
390For example, to retrieve the git hash of google3:
391
392```
393from get_llvm_hash import LLVMHash
394
395LLVMHash().GetGoogle3LLVMHash()
396```
397
398For example, to retrieve the git hash of a specific SVN version:
399
400```
401from get_llvm_hash import LLVMHash
402
403LLVMHash().GetLLVMHash(<svn_version>)
404```
405
406For example, to retrieve the latest google3 LLVM version:
407
408```
409from get_llvm_hash import GetGoogle3LLVMVersion
410
411GetGoogle3LLVMVersion(stable=True)
412```
413
414### `git_llvm_rev.py`
415
416This script is meant to synthesize LLVM revision numbers, and translate between
417these synthesized numbers and git SHAs. Usage should be straightforward:
418
419```
420~> ./git_llvm_rev.py --llvm_dir llvm-project-copy/ --rev r380000
4216f635f90929da9545dd696071a829a1a42f84b30
422~> ./git_llvm_rev.py --llvm_dir llvm-project-copy/ --sha 6f635f90929da9545dd696071a829a1a42f84b30
423r380000
424~> ./git_llvm_rev.py --llvm_dir llvm-project-copy/ --sha origin/some-branch
425r387778
426```
427
428**Tip**: if you put a symlink called `git-llvm-rev` to this script somewhere on
429your `$PATH`, you can also use it as `git llvm-rev`.
430
431### `get_upstream_patch.py`
432
433#### Usage
434
435This script updates the proper ChromeOS packages with LLVM patches of your choosing, and
436copies the patches into patch folders of the packages. This tool supports both git hash
437of commits as well as differential reviews.
438
439Usage:
440
441```
442./get_upstream_patch.py --chromeos_path /abs/path/to/chroot --start_sha llvm
443--sha 174c3eb69f19ff2d6a3eeae31d04afe77e62c021 --sha 174c3eb69f19ff2d6a3eeae31d04afe77e62c021
444--differential D123456
445```
446
447It tries to autodetect a lot of things (e.g., packages changed by each sha,
448their ebuild paths, the "start"/"end" revisions to set, etc.) By default the
449script creates a local patch. Use --create_cl option to create a CL instead. For
450more information, please see the `--help`
451
452### `revert_checker.py`
453
454**This script is copied from upstream LLVM. Please prefer to make upstream edits,
455rather than modifying this script. It's kept in a CrOS repo so we don't need an
456LLVM tree to `import` this from scripts here.**
457
458This script reports reverts which happen 'across' a certain LLVM commit.
459
460To clarify the meaning of 'across' with an example, if we had the following
461commit history (where `a -> b` notes that `b` is a direct child of `a`):
462
463123abc -> 223abc -> 323abc -> 423abc -> 523abc
464
465And where 423abc is a revert of 223abc, this revert is considered to be 'across'
466323abc. More generally, a revert A of a parent commit B is considered to be
467'across' a commit C if C is a parent of A and B is a parent of C.
468
469Usage example:
470
471```
472./revert_checker.py -C llvm-project-copy 123abc 223abc 323abc
473```
474
475In the above example, the tool will scan all commits between 123abc and 223abc,
476and all commits between 123abc and 323abc for reverts of commits which are
477parents of 123abc.
478
479### `nightly_revert_checker.py`
480
481This is an automated wrapper around `revert_checker.py`. It checks to see if any
482new reverts happened across toolchains that we're trying to ship since it was
483last run. If so, it either automatically cherry-picks the reverts, or sends
484emails to appropriate groups.
485
486Usage example for cherry-picking:
487```
488PYTHONPATH=../ ./nightly_revert_checker.py \
489 cherry-pick
490 --state_file state.json \
491 --llvm_dir llvm-project-copy \
492 --chromeos_dir ../../../../
493 [email protected]
494```
495
496Usage example for email:
497```
498PYTHONPATH=../ ./nightly_revert_checker.py \
499 email
500 --state_file state.json \
501 --llvm_dir llvm-project-copy \
502 --chromeos_dir ../../../../
503```
504
505### `bisect_clang_crashes.py`
506
507This script downloads clang crash diagnoses from
508gs://chromeos-toolchain-artifacts/clang-crash-diagnoses and sends them to 4c for
509bisection.
510
511Usage example:
512
513```
514$ ./bisect_clang_crashes.py --4c 4c-cli --state_file ./output/state.json
515```
516
517The above command downloads the artifacts of clang crash diagnoses and send them
518to 4c server for bisection. The summary of submitted jobs will be saved in
519output/state.json under the current path. The output directory will be created
520automatically if it does not exist yet. To get more information of the submitted
521jobs, please refer to go/4c-cli.
522
523### `upload_lexan_crashes_to_forcey.py`
524
525This script downloads clang crash diagnoses from Lexan's bucket and sends them
526to 4c for bisection.
527
528Usage example:
529
530```
531$ ./upload_lexan_crashes_to_forcey.py --4c 4c-cli \
532 --state_file ./output/state.json
533```
534
535The above command downloads the artifacts of clang crash diagnoses and send them
536to 4c server for bisection. The summary of submitted jobs will be saved in
537output/state.json under the current path. The output directory will be created
538automatically if it does not exist yet. To get more information of the submitted
539jobs, please refer to go/4c-cli.
540
541Note that it's recommended to 'seed' the state file with a most recent upload
542date. This can be done by running this tool *once* with a `--last_date` flag.
543This flag has the script override whatever's in the state file (if anything) and
544start submitting all crashes uploaded starting at the given day.
545
546### `werror_logs.py`
547
548This tool exists to help devs reason about `-Werror` instances that _would_
549break builds, were the `FORCE_DISABLE_WERROR` support in the compiler wrapper
550not enabled.
551
552Usage example:
553
554```
555$ ./werror_logs.py aggregate \
556 --directory=${repo}/out/sdk/tmp/portage/dev-cpp/gtest-1.13.0-r12/cros-artifacts
557```
558
559## `fetch_cq_size_diff.py`
560
561This script should be runnable both inside and outside of the chroot.
562
563This script exists to help users fill in the llvm-next testing matrix. It's
564capable of comparing the sizes of ChromeOS images, and the size of Chrome's
565debuginfo. An example of this is:
566
567```
568$ ./fetch_cq_size_diff.py --image gs \
569 gs://chromeos-image-archive/asurada-release/R122-15712.0.0/image.zip
570 gs://chromeos-image-archive/asurada-cq/R122-15712.0.0-92036-8761629109681962289/image.zip
571```
572
573For convenience, this script can also figure out what to compare from a CL, like
574so:
575
576```
577$ ./fetch_cq_size_diff.py --image cl \
578 https://chromium-review.googlesource.com/c/chromiumos/overlays/board-overlays/+/5126116/3
579```
580
581In the above case, this script will find a completed CQ build associated with
582PatchSet 3 of the given CL, and compare the `image.zip` generated by said build
583with the image.zip generated by a release builder for the same board. CQ
584attempts don't have to be entirely green for this; as long as there're a few
585green boards to pick from, this script should be able to make a comparison.
586