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