sammccall added a comment. TL;DR: can you try just excluding GCC's resource dir, rather than replacing it with clang's? I think that might solve your problem, and is probably something we should be doing automatically.
In D154903#4525329 <https://reviews.llvm.org/D154903#4525329>, @madscientist wrote: > Sorry for the delay in replying. I'll try to respond to the various points > you made: > > - I don't quite understand the first bullet, "more ways to initialize the > resource dir". As far as I can see there's only one place it's set. If my > change is using a "non-official" alternative to obtaining the resource dir > then certainly I would be happy to change my code to fix that The resource dir for a parse can be set in the following ways AFAIK, some of which are hopefully unreachable: - it can be set by passing -resource-dir to clangd, which gets propagated into the compile flags by CommandMangler - CommandMangler::detect() can choose it - the compile flags from the CDB can contain -resource-dir, overriding CommandMangler - the clang driver that we invoke as a library can detect it (hopefully never happens as a production CommandMangler always ensures -resource-dir is set) - it could be left unset if the clang driver fails to detect it (ditto) I'm not saying you're injecting it into the wrong place, I'm just saying adding a sixth path has a cost. > really the goal of my patch is to ensure that there is one single way to find > this directory and this is //preserved// by telling the compiler driver > explicitly where it is, rather than having multiple places attempting to > figure it out for themselves. As far as the driver is concerned, that's already the case before this patch: we endeavour to always pass `-resource-dir` to the driver. This patch attempts to sync that setting to/from another place, and doesn't entirely succeed (in the third case the resource dir used for parsing does not match the environment variable). > If using the built-in headers from one compiler with a different compiler is > fated to break in mysterious ways, does that mean you feel it's not useful to > try to use clangd in any project which doesn't use clang as its compiler? Not at all, but clangd should use clangd's built-in headers even if you're parsing a project that builds with another compiler. The built-in headers expose a (fairly) standard interface that code is expected to depend on, and their implementation is tightly coupled to the parser they ship with. For example, Clang's `<tgmath.h>` uses `__attribute__((__overloadable__))`, which GCC doesn't support, while gcc's `<tgmath.h>` uses `__builtin_tgmath`, which Clang doesn't support. These are used to implement e.g. generic `acosh()`, which is a public interface code can rely on. This is the difference between the built-in headers and the (rest of the) standard library: stdlibs generally try to be mostly portable between compilers and versions, the built-in headers are coupled. (In principle it's just as incorrect to try to use e.g. clang-12's builtin headers with clangd-13 - these really don't try to be portable). > I hope that this is not the case since (although the idea has been raised on > their mailing lists) there is not much work going on in GCC to create a > GCC-based LSP server. Although I do agree that there are no guarantees, in > reality clangd works very well in my GCC-based project if I replace the GCC > intrinsics directory with the clangd resource directory when the compiler > driver generates its list of built-in locations. Ahh, I finally think I understand what you're trying to do here... is this right? - you have a project that builds with GCC, using GCC's include path - you want to reuse that config with clangd, so you're using --query-driver to extract the include path list - the extracted list includes GCC's built-in headers, and these get inserted onto clangd's regular include path - now GCC's built-in headers shadow clangd's, so we have the "doesn't work" scenario described above - so you want to rewrite the list GCC's driver reports, replacing GCC's built-in headers with clangd's - and for that you need clangd's resource dir That would work but it's more than you need to do: clangd's resource dir is still on the search path (at the end), so if you simply **remove** GCC's built-in headers from the list then they'll stop being shadowed. Can you test if this works? This seems like a design oversight in query-driver. It should probably be doing this filtering by default, if there's a reasonable way to detect which entries are builtin includes. clang supports `-nobuiltininc` but GCC does not. On the other hand `clang --print-file-name=include` gives the built-in headers path, and the same works with GCC. Maybe we can invoke that separately and exclude it. > Regarding alternative solutions: > > - My environment is cross-platform between GNU/Linux (with various > distributions and on various platforms such as x86_64, arm64, and power9 and > power10), MacOS on both x86_64 and m1/m2, and Windows (10+) on x86_64. So > relying on things like /proc/$PPID/exe (or even bash!) is not ideal. > - Your solution requires me to know implicitly where (compared to the clangd > binary) the resource directory lives; that seems less reliable than having > clangd tell me. I don't quite understand the reassurance that these > implementation details are stable enough to assume to be "fact", compared > with the concern in the first bullet above about how they might change. > > Your solution also assumes there is only one version of clang installed on > the system; in fact my system has multiple versions so > `.../lib/clang/*/include` expands to multiple paths which parses incorrectly > (clangd assumes one directory per line). Of course I could have my compiler > driver run `clangd -version` and parse the output to find the right version; > my resource directory is `/usr/lib/clang/16` but the version is `16.0.0`... > it is do-able but it just seems increasingly hairy. > > At the moment I don't have a different compiler driver for clangd than the > standard compiler wrapper script that is provided via `compile_commands.json` > although of course I could create one and change my `.clangd` to point to it. > I was going to simply modify my compiler wrapper to DTRT if it discovered it > was being invoked with `-v` and `CLANGD_RESOURCE_DIR` was set. This all makes sense, working around this outside clangd is indeed going to get messy, especially when cross-platform. For general unsupportable messing-with-resource-dir stuff this might still be where we'd end up, but it sounds like we're actually talking about a problem that should be fixed for all users. > Also, on one of my systems clangd is apparently configured to use > posix_spawn() to invoke the compiler driver, which does not work with shell > scripts. But that just seems like a bug somewhere. I get: > > E[17:23:24.164] System include extraction: driver execution failed with > return code: -1 - 'posix_spawn failed: Exec format error'. Args: > [/home/pds/src/clangd/bin/qdriver.sh -E -x c++ - -v] > > although running that command from the shell prompt works fine. Yikes, from a cursory look it seems glibc posix_spawn is a bit of a mess... Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154903/new/ https://reviews.llvm.org/D154903 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits