Fix compilation database not listing every Swift source file

This makes SourceKit-LSP work correctly with multi-source-file targets.
pull/14264/head
Marco Rebhan 2 weeks ago
parent 1b54239a88
commit 46bbd885e4
No known key found for this signature in database
  1. 33
      mesonbuild/backend/ninjabackend.py

@ -508,6 +508,7 @@ class NinjaBackend(backends.Backend):
self.created_llvm_ir_rule = PerMachine(False, False) self.created_llvm_ir_rule = PerMachine(False, False)
self.rust_crates: T.Dict[str, RustCrate] = {} self.rust_crates: T.Dict[str, RustCrate] = {}
self.implicit_meson_outs: T.List[str] = [] self.implicit_meson_outs: T.List[str] = []
self.compdb_special_targets: T.List[T.Tuple[NinjaBuildElement, T.List[str]]] = []
self._uses_dyndeps = False self._uses_dyndeps = False
self._generated_header_cache: T.Dict[str, T.List[FileOrString]] = {} self._generated_header_cache: T.Dict[str, T.List[FileOrString]] = {}
# nvcc chokes on thin archives: # nvcc chokes on thin archives:
@ -746,9 +747,34 @@ class NinjaBackend(backends.Backend):
builddir = self.environment.get_build_dir() builddir = self.environment.get_build_dir()
try: try:
jsondb = subprocess.check_output(ninja_compdb, cwd=builddir) jsondb = subprocess.check_output(ninja_compdb, cwd=builddir)
with open(os.path.join(builddir, 'compile_commands.json'), 'wb') as f: jsondb_data = json.loads(jsondb)
f.write(jsondb) # Ninja's generated compilation database only includes the first input file for each build element. In order
except Exception: # to have LSPs like Swift's (which compiles multiple files per command invocation) pick it up, explicitly
# list all of the files here.
for t, extra_infilenames in self.compdb_special_targets:
arguments = []
for argument in t.rule.command:
# Most likely not 100% correct, but it doesn't have to be since most targets won't use this.
# Extend it if needed
if argument.s == '$in' and argument.quoting == Quoting.none:
arguments += t.infilenames
elif argument.s == '$out' and argument.quoting == Quoting.none:
arguments += t.outfilenames
elif argument.s.startswith('$') and argument.quoting == Quoting.none:
iterator = iter(t.elems)
while True:
k, v = next(iterator)
if k == argument.s[1:]:
arguments += v
break
else:
arguments.append(argument.s)
for file in itertools.chain(t.infilenames, extra_infilenames):
d = {'directory': builddir, 'arguments': arguments, 'file': file}
jsondb_data += [d]
with open(os.path.join(builddir, 'compile_commands.json'), 'w', encoding='utf-8') as f:
json.dump(jsondb_data, f, indent=2)
except (subprocess.CalledProcessError, OSError):
mlog.warning('Could not create compilation database.', fatal=False) mlog.warning('Could not create compilation database.', fatal=False)
# Get all generated headers. Any source file might need them so # Get all generated headers. Any source file might need them so
@ -2269,6 +2295,7 @@ class NinjaBackend(backends.Backend):
elem.add_item('ARGS', compile_args + header_imports + abs_generated + module_includes) elem.add_item('ARGS', compile_args + header_imports + abs_generated + module_includes)
elem.add_item('RUNDIR', rundir) elem.add_item('RUNDIR', rundir)
self.add_build(elem) self.add_build(elem)
self.compdb_special_targets.append((elem, rel_generated))
elem = NinjaBuildElement(self.all_outputs, out_module_name, rulename, abssrc) elem = NinjaBuildElement(self.all_outputs, out_module_name, rulename, abssrc)
elem.add_dep(in_module_files + rel_generated) elem.add_dep(in_module_files + rel_generated)
elem.add_item('ARGS', compile_args + abs_generated + module_includes + swiftc.get_mod_gen_args()) elem.add_item('ARGS', compile_args + abs_generated + module_includes + swiftc.get_mod_gen_args())

Loading…
Cancel
Save