| #!/usr/bin/env python3 |
| import argparse |
| import os |
| import re |
| import shlex |
| import subprocess |
| import sys |
| import textwrap |
| |
| def get_git_ref_or_rev(dir: str) -> str: |
| # Run 'git symbolic-ref -q --short HEAD || git rev-parse --short HEAD' |
| cmd_ref = 'git symbolic-ref -q --short HEAD' |
| ref = subprocess.run(shlex.split(cmd_ref), cwd=dir, text=True, |
| stdout=subprocess.PIPE) |
| if not ref.returncode: |
| return ref.stdout.strip() |
| cmd_rev = 'git rev-parse --short HEAD' |
| return subprocess.check_output(shlex.split(cmd_rev), cwd=dir, |
| text=True).strip() |
| |
| |
| def main(): |
| parser = argparse.ArgumentParser(description=textwrap.dedent(''' |
| This script builds two versions of BOLT (with the current and |
| previous revision) and sets up symlink for llvm-bolt-wrapper. |
| Passes the options through to llvm-bolt-wrapper. |
| ''')) |
| parser.add_argument('build_dir', nargs='?', default=os.getcwd(), |
| help='Path to BOLT build directory, default is current ' |
| 'directory') |
| parser.add_argument('--switch-back', default=False, action='store_true', |
| help='Checkout back to the starting revision') |
| args, wrapper_args = parser.parse_known_args() |
| bolt_path = f'{args.build_dir}/bin/llvm-bolt' |
| |
| source_dir = None |
| # find the repo directory |
| with open(f'{args.build_dir}/CMakeCache.txt') as f: |
| for line in f: |
| m = re.match(r'LLVM_SOURCE_DIR:STATIC=(.*)', line) |
| if m: |
| source_dir = m.groups()[0] |
| if not source_dir: |
| sys.exit("Source directory is not found") |
| |
| script_dir = os.path.dirname(os.path.abspath(__file__)) |
| wrapper_path = f'{script_dir}/llvm-bolt-wrapper.py' |
| # build the current commit |
| subprocess.run(shlex.split("cmake --build . --target llvm-bolt"), |
| cwd=args.build_dir) |
| # rename llvm-bolt |
| os.replace(bolt_path, f'{bolt_path}.new') |
| # memorize the old hash for logging |
| old_ref = get_git_ref_or_rev(source_dir) |
| |
| # determine whether a stash is needed |
| stash = subprocess.run(shlex.split("git status --porcelain"), cwd=source_dir, |
| stdout=subprocess.PIPE, stderr=subprocess.STDOUT, |
| text=True).stdout |
| if stash: |
| # save local changes before checkout |
| subprocess.run(shlex.split("git stash push -u"), cwd=source_dir) |
| # check out the previous commit |
| subprocess.run(shlex.split("git checkout -f HEAD^"), cwd=source_dir) |
| # get the parent commit hash for logging |
| new_ref = get_git_ref_or_rev(source_dir) |
| # build the previous commit |
| subprocess.run(shlex.split("cmake --build . --target llvm-bolt"), |
| cwd=args.build_dir) |
| # rename llvm-bolt |
| os.replace(bolt_path, f'{bolt_path}.old') |
| # set up llvm-bolt-wrapper.ini |
| ini = subprocess.check_output( |
| shlex.split( |
| f"{wrapper_path} {bolt_path}.old {bolt_path}.new") + wrapper_args, |
| text=True) |
| with open(f'{args.build_dir}/bin/llvm-bolt-wrapper.ini', 'w') as f: |
| f.write(ini) |
| # symlink llvm-bolt-wrapper |
| os.symlink(wrapper_path, bolt_path) |
| if args.switch_back: |
| if stash: |
| subprocess.run(shlex.split("git stash pop"), cwd=source_dir) |
| subprocess.run(shlex.split(f"git checkout {old_ref}"), cwd=source_dir) |
| else: |
| print(f"The repository {source_dir} has been switched from {old_ref} " |
| f"to {new_ref}. Local changes were stashed. Switch back using\n\t" |
| f"git checkout {old_ref}\n") |
| print(f"Build directory {args.build_dir} is ready to run BOLT tests, e.g.\n" |
| "\tbin/llvm-lit -sv tools/bolt/test\nor\n" |
| "\tbin/llvm-lit -sv tools/bolttests") |
| |
| |
| if __name__ == "__main__": |
| main() |