Clangd creates lots of errors when using different compiler (qcc)

I use the clangd LSP for my C development, and usually it works great.

I typically work with gcc, so I have the CLANGD_FLAGS environment variable set to --query-driver=C:/path/to/compilers/g*. This picks up on gcc/g++ well. I also use the compiledb Python module in order to generate compile_commands.json from my make rules. Typically this involves running py -m compiledb make all.

However, I’ve now started development on a C project using a different compiler (qcc) for work. This compiler is for the QNX operating system. Unfortunately, clangd hates this compiler and reports tons of errors (thinks NULL, EXIT_SUCCESS, etc, are undeclared identifiers despite being included).

I have tried setting my query driver to be the path to the qcc compiler. I’ve also generated the compile_commands.json file from the make <rule> output using compiledb. None of this has worked.

My project compiles just fine, and I still get some nice LSP features from clangd, but the errors everywhere are driving me insane. I would like to avoid using QNX’s IDE (it has less features than Neovim even with these LSP problems), and I can’t find anything online about using clangd with qcc except this GitHub issue, which is unsolved. I have also tried the suggested solution of a wrapper shell/bat script around qcc to have the output in gcc style to no avail.

Here’s what my main function looks like despite compiling just fine:

I know qcc is a much lesser used compiler, but I thought I’d give asking here a chance in case there are other QNX developers or people who have encountered similar issues with other compilers.

I think I had replied to your question but the issue you linked to reminded me of a hack I have in my compile commands generator - it replaces q++ with the g++ equivalent (qnx tools comes with both):

[re.compile(r"/q\+\+ "), r"/aarch64-unknown-nto-qnx7.1.0-g++ "],

…the reason for this is outlined in that thread and boils down to different flags and output formats between the two drivers (even thought they are effectively the same compiler). I think you can try doing a search/replace in your compile commands to see if replacing qcc/q++ with the gcc equivalent in the same dir helps with the whole query driver/extraction thing. I think it should.

1 Like

Thanks for the suggestion! This solution makes sense, but replacing qcc in my compile commands with aarch64-unknown-nto-qnx7.1.0-gcc hasn’t made a difference unfortunately. I still see the same warnings and errors, even after restarting my LSP.

My compile commands look like this in case you can spot something I’ve done incorrectly:

[
 {
  "directory": "/home/linguini/cuinspace/qnx-stack/packager/nto-x86_64-o",
  "arguments": [
   "/home/linguini/qnx710/host/linux/x86_64/usr/bin/aarch64-unknown-nto-qnx7.1.0-gcc",
   "-Vgcc_ntox86_64",
   "-c",
   "-Wc,-Wall",
   "-O2",
   "-std=gnu11",
   "-O2",
   "-Wall",
   "-Wextra",
   "-Wshadow",
   "-Wundef",
   "-Wformat=2",
   "-Wtrampolines",
   "-Wfloat-equal",
   "-Wbad-function-cast",
   "-Wstrict-prototypes",
   "-Wpacked",
   "-Wno-aggressive-loop-optimizations",
   "-Wmissing-prototypes",
   "-Winit-self",
   "-Wmissing-declarations",
   "-Wmissing-format-attribute",
   "-Wunreachable-code",
   "-Wshift-overflow=2",
   "-Wduplicated-cond",
   "-Wpointer-arith",
   "-Wwrite-strings",
   "-Wnested-externs",
   "-Wcast-align",
   "-Wredundant-decls",
   "-Werror=implicit-function-declaration",
   "-Wlogical-not-parentheses",
   "-Wlogical-op",
   "-Wold-style-definition",
   "-Wcast-qual",
   "-Wdouble-promotion",
   "-Wunsuffixed-float-constants",
   "-Wmissing-include-dirs",
   "-Wnormalized",
   "-Wdisabled-optimization",
   "-Wsuggest-attribute=const",
   "-DNDEBUG",
   "-I.",
   "-I/home/linguini/cuinspace/qnx-stack/packager/nto-x86_64-o",
   "-I/home/linguini/cuinspace/qnx-stack/packager",
   "-I/home/linguini/cuinspace/qnx-stack/packager/src",
   "-I/home/linguini/cuinspace/qnx-stack/packager/src/include",
   "-I/home/linguini/qnx710/target/qnx7/usr/include",
   "-DBUILDENV_qss",
   "/home/linguini/cuinspace/qnx-stack/packager/src/main.c"
  ],
  "file": "/home/linguini/cuinspace/qnx-stack/packager/src/main.c"
 },
 {
  "directory": "/home/linguini/cuinspace/qnx-stack/packager/nto-x86_64-o",
  "arguments": [
   "/home/linguini/qnx710/host/linux/x86_64/usr/bin/qcc",
   "-Vgcc_ntox86_64",
   "-c",
   "-Wc,-Wall",
   "-O2",
   "-std=gnu11",
   "-O2",
   "-Wall",
   "-Wextra",
   "-Wshadow",
   "-Wundef",
   "-Wformat=2",
   "-Wtrampolines",
   "-Wfloat-equal",
   "-Wbad-function-cast",
   "-Wstrict-prototypes",
   "-Wpacked",
   "-Wno-aggressive-loop-optimizations",
   "-Wmissing-prototypes",
   "-Winit-self",
   "-Wmissing-declarations",
   "-Wmissing-format-attribute",
   "-Wunreachable-code",
   "-Wshift-overflow=2",
   "-Wduplicated-cond",
   "-Wpointer-arith",
   "-Wwrite-strings",
   "-Wnested-externs",
   "-Wcast-align",
   "-Wredundant-decls",
   "-Werror=implicit-function-declaration",
   "-Wlogical-not-parentheses",
   "-Wlogical-op",
   "-Wold-style-definition",
   "-Wcast-qual",
   "-Wdouble-promotion",
   "-Wunsuffixed-float-constants",
   "-Wmissing-include-dirs",
   "-Wnormalized",
   "-Wdisabled-optimization",
   "-Wsuggest-attribute=const",
   "-DNDEBUG",
   "-I.",
   "-I/home/linguini/cuinspace/qnx-stack/packager/nto-x86_64-o",
   "-I/home/linguini/cuinspace/qnx-stack/packager",
   "-I/home/linguini/cuinspace/qnx-stack/packager/src",
   "-I/home/linguini/cuinspace/qnx-stack/packager/src/include",
   "-I/home/linguini/qnx710/target/qnx7/usr/include",
   "-DBUILDENV_qss",
   "/home/linguini/cuinspace/qnx-stack/packager/src/packet_types.c"
  ],
  "file": "/home/linguini/cuinspace/qnx-stack/packager/src/packet_types.c"
 }
]

I’ll assume you verified that arch64[verinfo]-gcc actually exists in that path (if not adjust according to your installation/version). More important, does your query driver arg to clangd exactly match (or valid wildcard) this new adjusted path? If not, try to make it match.

looks like you only fixed-up one of the entries in your DB…fine as long as you are only trying to edit main.c

I would remove all the warnings flags except the generic -Wall -Wextra - the reason is that clang and gcc have a slightly different set of specific warning flags they honor…and some warnings that ARE actually honored by your qcc/gcc compiler WILL not be liked by the clangd internal parser and it will just give up. It’s best to just get rid of all warnings flags except the generic ones IMHO. I really wish the internal clangd parser would just silently ignore warnings it does not recognize.

If this is still not working, turn on verbose logging for clangd/lsp and open the main.c in your editor and then examine the log. you should see info about flags extraction from the compiler and whether or not that worked, etc.

1 Like

To summarize:

  • I have verified the existence of ~/qnx710/host/linux/x86_64/usr/bin/aarch64-unknown-nto-qnx7.1.0-gcc
  • I have my query driver set to --query-driver=/usr/bin/gcc,/usr/bin/g++,~/qnx710/host/linux/x86_64/usr/bin/aarch64-unknown-nto-qnx7.1.0-gcc
  • I have changed all instances of qcc to the aarch64-unknown-nto-qnx... path in my compile_commands.json
  • I have removed all warning flags except -Wall -Wextra

I’ve also tried using the clangd-wrapper.sh you mentioned on your Reddit reply to my post. The language server starts correctly now that I’m using a Linux machine instead of dealing with Windows .bat files, but I’m still getting the same warnings as I did initially.

My logs don’t look abnormal; they are showing the correct arguments passed to clangd and the correct query driver.

from your log:

stack/fetcher/compile_commands.json\nV[20:17:52.511] System include extraction: not allowed driver

you are getting close! I think you need to provide the FULL path in the query-driver arg or possibly using ENV vars, but ~ is a shell expansion and won’t work in a path you provide to clangd. just go with the full path for now to see if it will work.

1 Like

Now I’m getting:

System include extraction: not allowed driver /home/linguini/qnx710/host/linux/x86_64/usr/bin/aarch64-unknown-nto-qnx7.1.0-gcc

I really appreciate your help by the way!

maybe try some wildcarding in you driver arg?..something like:

--query-driver=/home/linguini/qnx710/host/linux/x86_64/usr/bin/*gcc

…just to see if you can get clangd to allow it.

Still no luck :frowning:
I’ve tried with just the query driver as you wrote it, and although there’s no “not allowed driver” now, I’m not seeing any warnings disappear.
logs

uh, system extraction is working now:

System include extraction: target extracted: “aarch64-unknown-nto-qnx7.1.0”\nV[19:34:01.976] System include extraction: adding /home/linguini/qnx710/host/linux/x86_64/usr/lib/gcc/aarch64-unknown-nto-qnx7.1.0/8.3.0/include\nV[19:34:01.976] System include extraction: adding /home/linguini/qnx710/target/qnx7/usr/include\nI[19:34:01.976] System includes extractor: successfully executed /home/linguini/qnx710/host/linux/x86_64/usr/bin/aarch64-unknown-nto-qnx7.1.0-gcc\n\tgot includes:

…but now you still have a bunch of types errors. these cross compile environments are certainly NOT easy to get working, but it is possible…but it’s not immediately obvious to me what the issue is now.

oh…here are two defines to try forcing into your compile DB:

-D__QNXNTO__
-D__LITTLEENDIAN__

… I think the compiler might define these internally (thus the double underbar before/after) but they aren’t gleaned from extraction. It’s a long-shot, but worth a try.

since at some point you probably just want to write code, you can always consider hand-writing a clangd config file that just points at your host toolchain for everything (gcc) for forgo the qnx specific toolchain for clangd completely

1 Like

This was the solution! The final straw to get it to work! I’m going to attempt the same thing on my Windows machine now. Thank you so much!

nice! - someone should really document all these steps to get qnx working with clangd ;). It would be nice if clangd had a way to customize the extraction command (compiler/driver to extract flags mapping basically) to make this easier, but I guess for now it’s pretty easy to just manipulate json files with jq or python after generation.

1 Like

I agree! I’m glad someone else had this use-case because I figured this would be too niche to be documented elsewhere. Thanks again, I really appreciate your help