Last active
April 12, 2026 10:20
-
-
Save ichizok/9e34f02780f9837e6f0b0166367985a5 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| import json | |
| import subprocess | |
| import sys | |
| from argparse import ArgumentParser | |
| from os import path | |
| from tempfile import TemporaryDirectory | |
| def json_dump(obj, filename): | |
| with open(filename, "w") as f: | |
| json.dump(obj, f, indent=2) | |
| f.write("\n") | |
| def compiledb(build_log, work_dir): | |
| compile_commands_json = path.join(work_dir, "compile_commands.c.json") | |
| with open(build_log) as f: | |
| subprocess.run(["compiledb", "-o", compile_commands_json], stdin=f, check=True) | |
| with open(compile_commands_json) as f: | |
| return json.load(f) | |
| def xccompiledb(build_log, work_dir): | |
| compile_commands_json = path.join(work_dir, "compile_commands.m.json") | |
| r = [] | |
| with open(build_log) as f: | |
| compile_c = False | |
| dirname = "" | |
| for line in f: | |
| if line.startswith("CompileC "): | |
| compile_c = True | |
| elif line == "\n": | |
| compile_c = False | |
| elif compile_c and not line.isspace(): | |
| items = line.split() | |
| if items[0] == "cd": | |
| dirname = items[1] | |
| elif items[0].endswith("/bin/clang"): | |
| filename = items[items.index("-c") + 1] | |
| obj = { | |
| "directory": dirname, | |
| "arguments": items, | |
| "file": path.relpath(filename, dirname), | |
| } | |
| r += [obj] | |
| json_dump(r, compile_commands_json) | |
| return r | |
| def separate_build_log(build_log, build_c_log, build_m_log): | |
| with ( | |
| open(build_log) as f, | |
| open(build_c_log, "w") as fc, | |
| open(build_m_log, "w") as fm, | |
| ): | |
| xcodebuild = False | |
| for line in f: | |
| if xcodebuild or line.startswith("xcodebuild"): | |
| xcodebuild = True | |
| fm.write(line) | |
| else: | |
| fc.write(line) | |
| fc.write("\n") | |
| fm.write("\n") | |
| def main(): | |
| parser = ArgumentParser() | |
| parser.add_argument("build_log", nargs="?", type=str) | |
| args = parser.parse_args() | |
| with TemporaryDirectory() as work_dir: | |
| if args.build_log is None or args.build_log == "-": | |
| build_log = path.join(work_dir, "build.log") | |
| with open(build_log, "w") as f: | |
| for line in sys.stdin: | |
| f.write(line) | |
| sys.stdout.write(line) | |
| else: | |
| build_log = args.build_log | |
| if not path.isfile(build_log): | |
| raise FileNotFoundError(f"File not found: {build_log}") | |
| build_c_log = path.join(work_dir, "build.c.log") | |
| build_m_log = path.join(work_dir, "build.m.log") | |
| separate_build_log(build_log, build_c_log, build_m_log) | |
| r1 = compiledb(build_c_log, work_dir) | |
| r2 = xccompiledb(build_m_log, work_dir) | |
| json_dump(r1 + r2, "compile_commands.json") | |
| if __name__ == "__main__": | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment