17f928cbaSAmir Ayupov#!/usr/bin/env python3 27f928cbaSAmir Ayupovimport argparse 37f928cbaSAmir Ayupovimport os 47f928cbaSAmir Ayupovimport re 57f928cbaSAmir Ayupovimport shlex 67f928cbaSAmir Ayupovimport subprocess 77f928cbaSAmir Ayupovimport sys 87f928cbaSAmir Ayupovimport textwrap 97f928cbaSAmir Ayupov 10f98ee40fSTobias Hieta 11b346af6dSAmir Ayupovdef get_git_ref_or_rev(dir: str) -> str: 12b346af6dSAmir Ayupov # Run 'git symbolic-ref -q --short HEAD || git rev-parse --short HEAD' 13f98ee40fSTobias Hieta cmd_ref = "git symbolic-ref -q --short HEAD" 14f98ee40fSTobias Hieta ref = subprocess.run( 15f98ee40fSTobias Hieta shlex.split(cmd_ref), cwd=dir, text=True, stdout=subprocess.PIPE 16f98ee40fSTobias Hieta ) 17b346af6dSAmir Ayupov if not ref.returncode: 18b346af6dSAmir Ayupov return ref.stdout.strip() 19f98ee40fSTobias Hieta cmd_rev = "git rev-parse --short HEAD" 20f98ee40fSTobias Hieta return subprocess.check_output(shlex.split(cmd_rev), cwd=dir, text=True).strip() 21b346af6dSAmir Ayupov 227f928cbaSAmir Ayupov 237f928cbaSAmir Ayupovdef main(): 24f98ee40fSTobias Hieta parser = argparse.ArgumentParser( 25f98ee40fSTobias Hieta description=textwrap.dedent( 26f98ee40fSTobias Hieta """ 277f928cbaSAmir Ayupov This script builds two versions of BOLT (with the current and 287f928cbaSAmir Ayupov previous revision) and sets up symlink for llvm-bolt-wrapper. 297f928cbaSAmir Ayupov Passes the options through to llvm-bolt-wrapper. 30f98ee40fSTobias Hieta """ 31f98ee40fSTobias Hieta ) 32f98ee40fSTobias Hieta ) 33f98ee40fSTobias Hieta parser.add_argument( 34f98ee40fSTobias Hieta "build_dir", 35f98ee40fSTobias Hieta nargs="?", 36f98ee40fSTobias Hieta default=os.getcwd(), 37f98ee40fSTobias Hieta help="Path to BOLT build directory, default is current " "directory", 38f98ee40fSTobias Hieta ) 39f98ee40fSTobias Hieta parser.add_argument( 40f98ee40fSTobias Hieta "--switch-back", 41f98ee40fSTobias Hieta default=False, 42f98ee40fSTobias Hieta action="store_true", 43f98ee40fSTobias Hieta help="Checkout back to the starting revision", 44f98ee40fSTobias Hieta ) 45*3837e3e6SAmir Ayupov parser.add_argument( 46*3837e3e6SAmir Ayupov "--cmp-rev", 47*3837e3e6SAmir Ayupov default="HEAD^", 48*3837e3e6SAmir Ayupov help="Revision to checkout to compare vs HEAD", 49*3837e3e6SAmir Ayupov ) 507f928cbaSAmir Ayupov args, wrapper_args = parser.parse_known_args() 51f98ee40fSTobias Hieta bolt_path = f"{args.build_dir}/bin/llvm-bolt" 527f928cbaSAmir Ayupov 537f928cbaSAmir Ayupov source_dir = None 547f928cbaSAmir Ayupov # find the repo directory 55f98ee40fSTobias Hieta with open(f"{args.build_dir}/CMakeCache.txt") as f: 567f928cbaSAmir Ayupov for line in f: 57f98ee40fSTobias Hieta m = re.match(r"LLVM_SOURCE_DIR:STATIC=(.*)", line) 587f928cbaSAmir Ayupov if m: 597f928cbaSAmir Ayupov source_dir = m.groups()[0] 607f928cbaSAmir Ayupov if not source_dir: 617f928cbaSAmir Ayupov sys.exit("Source directory is not found") 627f928cbaSAmir Ayupov 63b346af6dSAmir Ayupov script_dir = os.path.dirname(os.path.abspath(__file__)) 64f98ee40fSTobias Hieta wrapper_path = f"{script_dir}/llvm-bolt-wrapper.py" 657f928cbaSAmir Ayupov # build the current commit 66f98ee40fSTobias Hieta subprocess.run( 67f98ee40fSTobias Hieta shlex.split("cmake --build . --target llvm-bolt"), cwd=args.build_dir 68f98ee40fSTobias Hieta ) 697f928cbaSAmir Ayupov # rename llvm-bolt 70f98ee40fSTobias Hieta os.replace(bolt_path, f"{bolt_path}.new") 71b346af6dSAmir Ayupov # memorize the old hash for logging 72b346af6dSAmir Ayupov old_ref = get_git_ref_or_rev(source_dir) 73b346af6dSAmir Ayupov 74330eec13SAmir Ayupov # determine whether a stash is needed 75f98ee40fSTobias Hieta stash = subprocess.run( 76f98ee40fSTobias Hieta shlex.split("git status --porcelain"), 77f98ee40fSTobias Hieta cwd=source_dir, 78f98ee40fSTobias Hieta stdout=subprocess.PIPE, 79f98ee40fSTobias Hieta stderr=subprocess.STDOUT, 80f98ee40fSTobias Hieta text=True, 81f98ee40fSTobias Hieta ).stdout 82330eec13SAmir Ayupov if stash: 83b346af6dSAmir Ayupov # save local changes before checkout 8462a034ccSAmir Ayupov subprocess.run(shlex.split("git stash push -u"), cwd=source_dir) 85*3837e3e6SAmir Ayupov # check out the previous/cmp commit 86*3837e3e6SAmir Ayupov subprocess.run(shlex.split(f"git checkout -f {args.cmp_rev}"), cwd=source_dir) 87b346af6dSAmir Ayupov # get the parent commit hash for logging 88b346af6dSAmir Ayupov new_ref = get_git_ref_or_rev(source_dir) 897f928cbaSAmir Ayupov # build the previous commit 90f98ee40fSTobias Hieta subprocess.run( 91f98ee40fSTobias Hieta shlex.split("cmake --build . --target llvm-bolt"), cwd=args.build_dir 92f98ee40fSTobias Hieta ) 937f928cbaSAmir Ayupov # rename llvm-bolt 94f98ee40fSTobias Hieta os.replace(bolt_path, f"{bolt_path}.old") 957f928cbaSAmir Ayupov # set up llvm-bolt-wrapper.ini 967f928cbaSAmir Ayupov ini = subprocess.check_output( 97f98ee40fSTobias Hieta shlex.split(f"{wrapper_path} {bolt_path}.old {bolt_path}.new") + wrapper_args, 98f98ee40fSTobias Hieta text=True, 99f98ee40fSTobias Hieta ) 100f98ee40fSTobias Hieta with open(f"{args.build_dir}/bin/llvm-bolt-wrapper.ini", "w") as f: 1017f928cbaSAmir Ayupov f.write(ini) 1027f928cbaSAmir Ayupov # symlink llvm-bolt-wrapper 1037f928cbaSAmir Ayupov os.symlink(wrapper_path, bolt_path) 104330eec13SAmir Ayupov if args.switch_back: 105330eec13SAmir Ayupov if stash: 106330eec13SAmir Ayupov subprocess.run(shlex.split("git stash pop"), cwd=source_dir) 107330eec13SAmir Ayupov subprocess.run(shlex.split(f"git checkout {old_ref}"), cwd=source_dir) 108330eec13SAmir Ayupov else: 109f98ee40fSTobias Hieta print( 110f98ee40fSTobias Hieta f"The repository {source_dir} has been switched from {old_ref} " 111b346af6dSAmir Ayupov f"to {new_ref}. Local changes were stashed. Switch back using\n\t" 112f98ee40fSTobias Hieta f"git checkout {old_ref}\n" 113f98ee40fSTobias Hieta ) 114f98ee40fSTobias Hieta print( 115f98ee40fSTobias Hieta f"Build directory {args.build_dir} is ready to run BOLT tests, e.g.\n" 116330eec13SAmir Ayupov "\tbin/llvm-lit -sv tools/bolt/test\nor\n" 117f98ee40fSTobias Hieta "\tbin/llvm-lit -sv tools/bolttests" 118f98ee40fSTobias Hieta ) 1197f928cbaSAmir Ayupov 1207f928cbaSAmir Ayupov 1217f928cbaSAmir Ayupovif __name__ == "__main__": 1227f928cbaSAmir Ayupov main() 123