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 remove all patches that no longer apply:
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 remove_patches
167```
168
169For example, to bisect a failing patch and stop at the first bisected patch:
170
171```
172$ ./patch_manager.py \
173 --svn_version 367622 \
174 --patch_metadata_file /abs/path/to/patch/file \
175 --src_path /abs/path/to/src/tree \
176 --failure_mode bisect_patches \
177 --good_svn_version 365631
178```
179
180For example, to bisect a failing patch and then continue bisecting the rest of
181the failed patches:
182
183```
184$ ./patch_manager.py \
185 --svn_version 367622 \
186 --patch_metadata_file /abs/path/to/patch/file \
187 --src_path /abs/path/to/src/tree \
188 --failure_mode bisect_patches \
189 --good_svn_version 365631 \
190 --continue_bisection True
191```
192
193## LLVM Bisection
194
195### `llvm_bisection.py`
196
197#### Usage
198
199This script is used to bisect a bad revision of LLVM. After the script finishes,
200the user requires to run the script again to continue the bisection. Intially,
201the script creates a JSON file that does not exist which then continues
202bisection (after invoking the script again) based off of the JSON file.
203
204For example, assuming the revision 369420 is the bad revision:
205
206```
207$ ./llvm_bisection.py \
208 --parallel 3 \
209 --start_rev 369410 \
210 --end_rev 369420 \
211 --last_tested /abs/path/to/tryjob/file/ \
212 --extra_change_lists 513590 \
213 --builder eve-release-tryjob \
214 --options latest-toolchain
215```
216
217The above example bisects the bad revision (369420), starting from the good
218revision 369410 and launching 3 tryjobs in between if possible (`--parallel`).
219Here, the `--last_tested` path is a path to a JSON file that does not exist. The
220tryjobs are tested on the eve board. `--extra_change_lists` and `--options`
221indicate what parameters to pass into launching a tryjob.
222
223For help with the command line arguments of the script, run:
224
225```
226$ ./llvm_bisection.py --help
227```
228
229### `auto_llvm_bisection.py`
230
231#### Usage
232
233This script automates the LLVM bisection process by using `cros buildresult` to
234update the status of each tryjob.
235
236An example when this script would be used to do LLVM bisection overnight
237because tryjobs take very long to finish.
238
239For example, assuming the good revision is 369410 and the bad revision is
240369420, then:
241
242```
243$ ./auto_llvm_bisection.py --start_rev 369410 --end_rev 369420 \
244 --last_tested /abs/path/to/last_tested_file.json \
245 --extra_change_lists 513590 1394249 \
246 --options latest-toolchain nochromesdk \
247 --chroot_path /path/to/chromeos/chroot \
248 --builder eve-release-tryjob
249```
250
251The example above bisects LLVM between revision 369410 and 369420. If the file
252exists, the script resumes bisection. Otherwise, the script creates the file
253provided by `--last_tested`. `--extra_change_lists` and `--options` are used for
254each tryjob when being submitted. Lastly, the tryjobs are launched for the board
255provided by `--builder` (in this example, for the eve board).
256
257For help with the command line arguments of the script, run:
258
259```
260$ ./auto_llvm_bisection.py --help
261```
262
263### `update_tryjob_status.py`
264
265#### Usage
266
267This script updates a tryjob's 'status' value when bisecting LLVM. This script
268can use the file that was created by `llvm_bisection.py`.
269
270An example when this script would be used is when the result of tryjob that was
271launched was 'fail' (due to flaky infra) but it should really have been
272'success'.
273
274For example, to update a tryjob's 'status' to 'good':
275
276```
277$ ./update_tryjob_status.py \
278 --set_status good \
279 --revision 369412 \
280 --status_file /abs/path/to/tryjob/file
281```
282
283The above example uses the file in `--status_file` to update a tryjob in that
284file that tested the revision 369412 and sets its 'status' value to 'good'.
285
286For help with the command line arguments of the script, run:
287
288```
289$ ./update_tryjob_status.py --help
290```
291
292For example, to update a tryjob's 'status' to 'bad':
293
294```
295$ ./update_tryjob_status.py \
296 --set_status bad \
297 --revision 369412 \
298 --status_file /abs/path/to/tryjob/file
299```
300
301For example, to update a tryjob's 'status' to 'pending':
302
303```
304$ ./update_tryjob_status.py \
305 --set_status pending \
306 --revision 369412 \
307 --status_file /abs/path/to/tryjob/file
308```
309
310For example, to update a tryjob's 'status' to 'skip':
311
312```
313$ ./update_tryjob_status.py \
314 --set_status skip \
315 --revision 369412 \
316 --status_file /abs/path/to/tryjob/file
317```
318
319For example, to update a tryjob's 'status' based off a custom script exit code:
320
321```
322$ ./update_tryjob_status.py \
323 --set_status custom_script \
324 --revision 369412 \
325 --status_file /abs/path/to/tryjob/file \
326 --custom_script /abs/path/to/script.py
327```
328
329### `modify_a_tryjob.py`
330
331#### Usage
332
333This script modifies a tryjob directly given an already created tryjob file when
334bisecting LLVM. The file created by `llvm_bisection.py` can be used in this
335script.
336
337An example when this script would be used is when a tryjob needs to be manually
338added.
339
340For example:
341
342```
343$ ./modify_a_tryjob.py \
344 --modify_a_tryjob add \
345 --revision 369416 \
346 --extra_change_lists 513590 \
347 --options latest-toolchain \
348 --builder eve-release-tryjob \
349 --status_file /abs/path/to/tryjob/file
350```
351
352The above example creates a tryjob that tests revision 369416 on the eve board,
353passing in the extra arguments (`--extra_change_lists` and `--options`). The
354tryjob is then inserted into the file passed in via `--status_file`.
355
356For help with the command line arguments of the script, run:
357
358```
359$ ./modify_a_tryjob.py --help
360```
361
362For example, to remove a tryjob that tested revision 369412:
363
364```
365$ ./modify_a_tryjob.py \
366 --modify_a_tryjob remove \
367 --revision 369412 \
368 --status_file /abs/path/to/tryjob/file
369```
370
371For example, to relaunch a tryjob that tested revision 369418:
372
373```
374$ ./modify_a_tryjob.py \
375 --modify_a_tryjob relaunch \
376 --revision 369418 \
377 --status_file /abs/path/to/tryjob/file
378```
379
380## Other Helpful Scripts
381
382### `get_llvm_hash.py`
383
384#### Usage
385
386The script has a class that deals with retrieving either the top of trunk git
387hash of LLVM, the git hash of google3, or a specific git hash of a SVN version.
388It also has other functions when dealing with a git hash of LLVM.
389
390In addition, it has a function to retrieve the latest google3 LLVM version.
391
392For example, to retrieve the top of trunk git hash of LLVM:
393
394```
395from get_llvm_hash import LLVMHash
396
397LLVMHash().GetTopOfTrunkGitHash()
398```
399
400For example, to retrieve the git hash of google3:
401
402```
403from get_llvm_hash import LLVMHash
404
405LLVMHash().GetGoogle3LLVMHash()
406```
407
408For example, to retrieve the git hash of a specific SVN version:
409
410```
411from get_llvm_hash import LLVMHash
412
413LLVMHash().GetLLVMHash(<svn_version>)
414```
415
416For example, to retrieve the latest google3 LLVM version:
417
418```
419from get_llvm_hash import GetGoogle3LLVMVersion
420
421GetGoogle3LLVMVersion(stable=True)
422```
423
424### `git_llvm_rev.py`
425
426This script is meant to synthesize LLVM revision numbers, and translate between
427these synthesized numbers and git SHAs. Usage should be straightforward:
428
429```
430~> ./git_llvm_rev.py --llvm_dir llvm-project-copy/ --rev r380000
4316f635f90929da9545dd696071a829a1a42f84b30
432~> ./git_llvm_rev.py --llvm_dir llvm-project-copy/ --sha 6f635f90929da9545dd696071a829a1a42f84b30
433r380000
434~> ./git_llvm_rev.py --llvm_dir llvm-project-copy/ --sha origin/some-branch
435r387778
436```
437
438**Tip**: if you put a symlink called `git-llvm-rev` to this script somewhere on
439your `$PATH`, you can also use it as `git llvm-rev`.
440
441### `get_upstream_patch.py`
442
443#### Usage
444
445This script updates the proper ChromeOS packages with LLVM patches of your choosing, and
446copies the patches into patch folders of the packages. This tool supports both git hash
447of commits as well as differential reviews.
448
449Usage:
450
451```
452./get_upstream_patch.py --chroot_path /abs/path/to/chroot --start_sha llvm
453--sha 174c3eb69f19ff2d6a3eeae31d04afe77e62c021 --sha 174c3eb69f19ff2d6a3eeae31d04afe77e62c021
454--differential D123456
455```
456
457It tries to autodetect a lot of things (e.g., packages changed by each sha,
458their ebuild paths, the "start"/"end" revisions to set, etc.) By default the
459script creates a local patch. Use --create_cl option to create a CL instead. For
460more information, please see the `--help`
461
462### `revert_checker.py`
463
464**This script is copied from upstream LLVM. Please prefer to make upstream edits,
465rather than modifying this script. It's kept in a CrOS repo so we don't need an
466LLVM tree to `import` this from scripts here.**
467
468This script reports reverts which happen 'across' a certain LLVM commit.
469
470To clarify the meaning of 'across' with an example, if we had the following
471commit history (where `a -> b` notes that `b` is a direct child of `a`):
472
473123abc -> 223abc -> 323abc -> 423abc -> 523abc
474
475And where 423abc is a revert of 223abc, this revert is considered to be 'across'
476323abc. More generally, a revert A of a parent commit B is considered to be
477'across' a commit C if C is a parent of A and B is a parent of C.
478
479Usage example:
480
481```
482./revert_checker.py -C llvm-project-copy 123abc 223abc 323abc
483```
484
485In the above example, the tool will scan all commits between 123abc and 223abc,
486and all commits between 123abc and 323abc for reverts of commits which are
487parents of 123abc.
488
489### `nightly_revert_checker.py`
490
491This is an automated wrapper around `revert_checker.py`. It checks to see if any
492new reverts happened across toolchains that we're trying to ship since it was
493last run. If so, it either automatically cherry-picks the reverts, or sends
494emails to appropriate groups.
495
496Usage example for cherry-picking:
497```
498PYTHONPATH=../ ./nightly_revert_checker.py \
499 cherry-pick
500 --state_file state.json \
501 --llvm_dir llvm-project-copy \
502 --chromeos_dir ../../../../
503 --reviewers=chromium-os-mage@google.com
504```
505
506Usage example for email:
507```
508PYTHONPATH=../ ./nightly_revert_checker.py \
509 email
510 --state_file state.json \
511 --llvm_dir llvm-project-copy \
512 --chromeos_dir ../../../../
513```
514
515### `bisect_clang_crashes.py`
516
517This script downloads clang crash diagnoses from
518gs://chromeos-toolchain-artifacts/clang-crash-diagnoses and sends them to 4c for
519bisection.
520
521Usage example:
522
523```
524$ ./bisect_clang_crashes.py --4c 4c-cli --state_file ./output/state.json
525```
526
527The above command downloads the artifacts of clang crash diagnoses and send them
528to 4c server for bisection. The summary of submitted jobs will be saved in
529output/state.json under the current path. The output directory will be created
530automatically if it does not exist yet. To get more information of the submitted
531jobs, please refer to go/4c-cli.
532
533### `upload_lexan_crashes_to_forcey.py`
534
535This script downloads clang crash diagnoses from Lexan's bucket and sends them
536to 4c for bisection.
537
538Usage example:
539
540```
541$ ./upload_lexan_crashes_to_forcey.py --4c 4c-cli \
542 --state_file ./output/state.json
543```
544
545The above command downloads the artifacts of clang crash diagnoses and send them
546to 4c server for bisection. The summary of submitted jobs will be saved in
547output/state.json under the current path. The output directory will be created
548automatically if it does not exist yet. To get more information of the submitted
549jobs, please refer to go/4c-cli.
550
551Note that it's recommended to 'seed' the state file with a most recent upload
552date. This can be done by running this tool *once* with a `--last_date` flag.
553This flag has the script override whatever's in the state file (if anything) and
554start submitting all crashes uploaded starting at the given day.
555