Skip to content

Instantly share code, notes, and snippets.

@micahcc
Created September 14, 2021 19:04
Show Gist options
  • Save micahcc/bb31e4c91696537f5c0d8b9c8f964255 to your computer and use it in GitHub Desktop.
Save micahcc/bb31e4c91696537f5c0d8b9c8f964255 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
import json
import subprocess
import os
import sys
def resolve_depset_to_paths(artifacts, path_fragments, depset):
all_inputs = []
for artifact_id in depset["directArtifactIds"]:
artifact = artifacts[artifact_id]
path = []
path_fragment_id = artifact.get("pathFragmentId")
while path_fragment_id is not None:
path_fragment = path_fragments[path_fragment_id]
path.append(path_fragment["label"])
path_fragment_id = path_fragment.get("parentId")
path = os.path.join(*reversed(path))
all_inputs.append(path)
return all_inputs
def main():
ROOT = os.path.realpath(
os.path.join(os.path.dirname(os.path.realpath(__file__)), "..")
)
# TODO do we need CppLink CppLTOIndexing ?
cmd = [
"bazel",
"aquery",
'mnemonic("CppCompile", //...)',
"--output",
"jsonproto",
]
ret = subprocess.check_output(cmd)
ret = ret.decode("utf-8")
in_data = json.loads(ret)
dep_set_of_files = {d["id"]: d for d in in_data["depSetOfFiles"]}
artifacts = {d["id"]: d for d in in_data["artifacts"]}
path_fragments = {d["id"]: d for d in in_data["pathFragments"]}
outdata = []
for action in in_data["actions"]:
# resolve input paths
all_inputs = []
for ds_id in action["inputDepSetIds"]:
depset = dep_set_of_files[ds_id]
all_inputs.extend(
resolve_depset_to_paths(artifacts, path_fragments, depset)
)
for ds_id in depset.get("transitiveDepSetIds", []):
all_inputs.extend(
resolve_depset_to_paths(
artifacts, path_fragments, dep_set_of_files[ds_id]
)
)
# resolve output path
artifact = artifacts[action["primaryOutputId"]]
path_fragment_id = artifact["pathFragmentId"]
path_fragment = path_fragments[path_fragment_id]
output_path = []
while "parentId" in path_fragment:
output_path.append(path_fragment["label"])
path_fragment = path_fragments[path_fragment["parentId"]]
output_path = os.path.join(*reversed(output_path))
cc_inputs = list(
filter(
lambda x: x.endswith(".c")
or x.endswith(".cxx")
or x.endswith(".cc")
or x.endswith(".cpp"),
all_inputs,
)
)
assert len(cc_inputs) == 1
command = action["arguments"]
cc_inputs[0] in command, "Input should be on the command line"
outdata.append(
{
"command": command,
"directory": ROOT,
"file": cc_inputs[0],
"output": output_path,
}
)
outfile = os.path.join(ROOT, "compile_commands.json")
with open(outfile, "w") as f:
json.dump(outdata, f)
if __name__ == "__main__":
sys.exit(main())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment