The problem is that in the "arguments"
field of the compile_commands.json
entry, "-I /home/user/project/include"
is a single argument. (So is "-o example"
though that doesn't cause any harm in this case.)
That means the command that's executed will be as if you had written:
$ /usr/bin/clang++ "-I /home/user/project/include" "-o example" /home/user/project/common/example.cc
(note the quotes around "-I /home/user/project/include"
and "-o example"
).
If you run that command, that gives the same 'common/example.hh' file not found clang(pp_file_not_found)
error. Basically, the quotes make clang think that the argument to -I
starts with a space character, which then does not resolve as a path.
The solution is to place each token of the command line in a separate element of "arguments"
:
[
{
"directory": "/home/user/project",
"file": "/home/user/project/common/example.cc",
"arguments": [
"/usr/bin/clang++",
"-I",
"/home/user/project/include",
"-o",
"example",
"/home/user/project/common/example.cc"
],
"output": "example"
}
]
The reason "arguments"
is interpreted in this way is that the format specification for compile_commands.json
describes "arguments"
as follows:
arguments: The compile command argv as list of strings. This should run the compilation step for the translation unit file
. arguments[0]
should be the executable name, such as clang++
. Arguments should not be escaped, but ready to pass to execvp()
.
Basically, "arguments"
are expected to be the command line arguments as a shell would parse them and pass them to the argv
of a program. Since arguments are space-separated, the only way a single argument can contain an internal space is if that argument was quoted on the command line.
Finally, I'll note that compile_commands.json
files are generally not meant to be written by hand, but instead generated by a tool (usually your project's build system or something related). See https://clangd.llvm.org/installation#project-setup for a list of commonly used tools to generate them.
If you must hand-write a compile_commands.json
, it's probably easier to use "command"
instead of "arguments"
(refer to the spec for an example), precisely to avoid issues like this.