xref: /llvm-project/bolt/utils/nfc-check-setup.py (revision 3837e3e6cecb8edbe3fdb2c73fb6cea6a8dc1a28)
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