clang-tools 20.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
29import Queue
30import shutil
31import subprocess
32import sys
33import tempfile
34import threading
35
36
37def find_compilation_database(path):
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.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()
def MergeSymbols(directory, args)
def run_find_all_symbols(args, tmpdir, build_path, queue)