clang-tools 22.0.0git
run-find-all-symbols.py
Go to the documentation of this file.
1#!/usr/bin/env python
2#
3# =- run-find-all-symbols.py - Parallel find-all-symbols runner -*- python -*-=#
4#
5# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
6# See https://llvm.org/LICENSE.txt for license information.
7# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8#
9# ===------------------------------------------------------------------------===#
10
11"""
12Parallel find-all-symbols runner
13================================
14
15Runs find-all-symbols over all files in a compilation database.
16
17Example invocations.
18- Run find-all-symbols on all files in the current working directory.
19 run-find-all-symbols.py <source-file>
20
21Compilation database setup:
22http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html
23"""
24
25import argparse
26import json
27import multiprocessing
28import os
29from queue import Queue
30import shutil
31import subprocess
32import sys
33import tempfile
34import threading
35
36
38 """Adjusts the directory until a compilation database is found."""
39 result = "./"
40 while not os.path.isfile(os.path.join(result, path)):
41 if os.path.realpath(result) == "/":
42 print("Error: could not find compilation database.")
43 sys.exit(1)
44 result += "../"
45 return os.path.realpath(result)
46
47
48def MergeSymbols(directory, args):
49 """Merge all symbol files (yaml) in a given directory into a single file."""
50 invocation = [args.binary, "-merge-dir=" + directory, args.saving_path]
51 subprocess.call(invocation)
52 print("Merge is finished. Saving results in " + args.saving_path)
53
54
55def run_find_all_symbols(args, tmpdir, build_path, queue):
56 """Takes filenames out of queue and runs find-all-symbols on them."""
57 while True:
58 name = queue.get()
59 invocation = [args.binary, name, "-output-dir=" + tmpdir, "-p=" + build_path]
60 sys.stdout.write(" ".join(invocation) + "\n")
61 subprocess.call(invocation)
62 queue.task_done()
63
64
65def main():
66 parser = argparse.ArgumentParser(
67 description="Runs find-all-symbols over all" "files in a compilation database."
68 )
69 parser.add_argument(
70 "-binary",
71 metavar="PATH",
72 default="./bin/find-all-symbols",
73 help="path to find-all-symbols binary",
74 )
75 parser.add_argument(
76 "-j", type=int, default=0, help="number of instances to be run in parallel."
77 )
78 parser.add_argument(
79 "-p", dest="build_path", help="path used to read a compilation database."
80 )
81 parser.add_argument(
82 "-saving-path", default="./find_all_symbols_db.yaml", help="result saving path"
83 )
84 args = parser.parse_args()
85
86 db_path = "compile_commands.json"
87
88 if args.build_path is not None:
89 build_path = args.build_path
90 else:
91 build_path = find_compilation_database(db_path)
92
93 tmpdir = tempfile.mkdtemp()
94
95 # Load the database and extract all files.
96 database = json.load(open(os.path.join(build_path, db_path)))
97 files = [entry["file"] for entry in database]
98
99 # Filter out .rc files on Windows. CMake includes them for some reason.
100 files = [f for f in files if not f.endswith(".rc")]
101
102 max_task = args.j
103 if max_task == 0:
104 max_task = multiprocessing.cpu_count()
105
106 try:
107 # Spin up a bunch of tidy-launching threads.
108 queue = Queue(max_task)
109 for _ in range(max_task):
110 t = threading.Thread(
111 target=run_find_all_symbols, args=(args, tmpdir, build_path, queue)
112 )
113 t.daemon = True
114 t.start()
115
116 # Fill the queue with files.
117 for name in files:
118 queue.put(name)
119
120 # Wait for all threads to be done.
121 queue.join()
122
123 MergeSymbols(tmpdir, args)
124
125 except KeyboardInterrupt:
126 # This is a sad hack. Unfortunately subprocess goes
127 # bonkers with ctrl-c and we start forking merrily.
128 print("\nCtrl-C detected, goodbye.")
129 os.kill(0, 9)
130
131
132if __name__ == "__main__":
133 main()
MergeSymbols(directory, args)
run_find_all_symbols(args, tmpdir, build_path, queue)