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