[clangd-dev] VS Code Clangd and CMake integration

Michael Steinberg via clangd-dev clangd-dev at lists.llvm.org
Thu Nov 29 09:26:56 PST 2018


Howdy,

the "domain" of the two tools compiler and language server are 
completely different, where the former usually lives in the build-tree, 
the latter usually lives with the user inside the source tree... So I 
would argue that the default lookup rather becomes the unusual case...

That being said, after long hard times the CMakeTools developer together 
with the Microsoft C++ extension team came up with an approach exactly 
like you depict somewhere around mid-year. But since the MS Extensions 
don't support "find references", it was still useless - which is why I'm 
currently using cquery. I bet it would be an easy thing to click into 
that interfacing for the clangd extension as well.

Regards,
Michael

Am 29.11.2018 um 17:36 schrieb Anton Södergren via clangd-dev:
>
>     But in VSCode, the build system is just another plugin that may or
>     may not be installed, so a decoupled design seems most likely to
>     work in many configurations.
>
> If we could find a solution, it would of course be completely 
> optional. Clangd would use its normal discovery mechanism of 
> compile_commands.json, unless another plugin tells it to use a 
> specific file or build dir. Maybe the build system extension could 
> even give Clangd separate info for each C++ file if we want to be 
> really flexible, but again, I don't know exactly how that info would 
> be sent to Clangd. I agree that it's not reasonable that this info 
> would be shared between different projects.
>
> Something like this would be ideal:
>
>  1. User opens a folder
>  2. CMake runs
>  3. A compile_commands.json is generated
>  4. CMake Tools somehow tells Clangd where to find the file (this one
>     is where the problem lies)
>  5. Repeat steps 2-4 whenever CMake needs to generate again
>
>
>     Clangd needs to be able to determine the compile command given a
>     filename, at any time, within the clangd process (i.e. without
>     exchanging LSP messages with the editor).
>
> I'll admit that this sounds rather tricky. But the build plugin would 
> only need to notify Clangd when it actually generates its 
> compile_commands.json, after which Clangd could keep and reuse that state.
>
>     It is in fact possible as a command flag (it's spelled
>     -compile-commands-dir).
>
> Would this only be passed once when the process starts and then never 
> touched again? If so, then yeah this obviously doesn't work.
>
>     each tool (clangd, clang-tidy etc) needs to get this configuration
>     in some appropriate way, it's not shared (whereas all clang-based
>     tools share discovery logic for compile_commands.json)
>
> Yeah, this does sound like a scalability issue if a user wants to use 
> multiple Clang tools, as the build system extension would have to 
> communicate with every one of them.
>
>     Maybe one idea is to stick to compile_commands.json but extend the
>     way they are discovered, e.g. let the Cmake Tools plugin notify
>     Clangd that a certain compile_commands file is relevant and should
>     be considered, even if it's not in an ancestor dir of the source file.
>
> This sounds like a fairly reasonable compromise. But then again, we 
> would still need a way for the build system extension to communicate 
> this to Clangd.
>
> Given the following circumstances:
>
>   * There is always only one Clangd instance which is shared between
>     different projects/folders
>   * Command line arguments can only be passed to Clangd when launching it
>   * Command line arguments passed to Clangd will affect all different
>     projects/folders
>   * The only ways for VSCode to communicate with Clangd after
>     launching it is via LSP or files that both VSCode and Clangd
>     already know about
>   * LSP can not be used for this purpose
>
> then this problem might not actually be possible to solve. If all of 
> this would mean completely redesigning the way that Clangd is invoked, 
> then yeah maybe generating a symlink is the only way to go about this. 
> I'm still not fond of polluting the source tree with something that is 
> not super obvious that it was generated by an IDE/editor or what 
> generated it, but maybe this is just an inherent downside of using LSP 
> rather than an integrated C++ library (not trying to discredit your 
> work, it's still a great project!)...
> Then the question is how the build system extension would decide where 
> to put the symlink. Would it always end up in the root folder? Or 
> something like CMAKE_SOURCE_DIR (these two are often the same, but I 
> guess it's a good idea to be specific)? What did you mean by 
> symlinking src/.build to build/? Sorry, I never really use symlinks so 
> I'm not very familiar with them. It seems like CMake tool actually has 
> a config option to place a copy (not a symlink) of 
> compile_commands.json in a path specified by the user in the config. 
> Though I think this has to be done automatically without the user 
> having to go into the config and set it up, maybe after clicking a 
> "yes" button that pops up in VSCode or something. Otherwise most users 
> will probably just assume that the two plugins simply don't work well 
> together (like I did). Could even have a notification to warn the user 
> to include the file in their VCS ignore file. Of course, this is in 
> the hands of CMake Tools and other build system extensions, just 
> thought it was relevant to the discussion.
>
>     It's... not trivial. (Other clang tools don't handle this as they
>     tend to be batch)
>     So we'll fix it, but it might take a little time :-)
>
> I'm not too worried about time, just good to hear that someone is 
> working on it. :)
>
>
>
>
> On Wed, 28 Nov 2018 at 23:59, Sam McCall <sammccall at google.com 
> <mailto:sammccall at google.com>> wrote:
>
>     On Wed, Nov 28, 2018, 23:00 Anton Södergren
>     <anton.sodergren at gmail.com <mailto:anton.sodergren at gmail.com> wrote:
>
>             I'm not familiar with CMake Tools, I guess it helps with
>             editing CMakeLists, CMake configs, and running
>             configure/generate?
>
>         Except for the file editing part (that's handled by another
>         extension), you're pretty much right. It also allows for
>         building and launching debuggers. But it's the
>         configure/generate part that's the most interesting in our case.
>
>             Clangd works like other clang-based tools. Starting at the
>             source file in question, it walks up directories until it
>             finds compile_commands.json
>             <https://clang.llvm.org/docs/JSONCompilationDatabase.html>.
>
>         So it turned out that it indeed seemed to generate a
>         compile_commands.json file in the build folder (at least
>         yesterday, today it doesn't seem to work well at all). I tried
>         copying that file over to my project root folder and Clangd
>         found it and started working correctly indeed!
>
>             The current best-practice is to manually create a symlink
>             src/compile_commands.json -> build/compile_commands.json.
>             I think symlinking src/.build to build/ is a slightly more
>             principled approach, but something still has to create a
>             symlink. (Maybe we could get CMake or CMake Tools to do it?)
>
>         While this is a possible approach, I think is sounds a little
>         unwieldy (though that might just be personal preference). When
>         I looked around a bit more, I saw that the Clang tooling docs
>         <https://clang.llvm.org/docs/HowToSetupToolingForLLVM.html>
>         mentioned that it's possible to pass the build path directly
>         to Clang tools with a -p parameter, is this possible in Clangd
>         too?
>
>     It is in fact possible as a command flag (it's spelled
>     -compile-commands-dir). It works in a pinch, but it's a subtly
>     broken idea and I don't think it's the right long-term direction.
>
>     1) a clangd instance is typically 1:1 with an editor session. But
>     an editor can open files from multiple projects, so what should
>     the flag value be?
>     2) how does the editor know which dir to pass to clangd? If it's
>     an editor preference, how does this work for users who work in
>     different projects at different times?
>     3) each tool (clangd, clang-tidy etc) needs to get this
>     configuration in some appropriate way, it's not shared (whereas
>     all clang-based tools share discovery logic for compile_commands.json)
>
>     Requiring the symlink (and adding it to gitignore etc) is a little
>     fiddly and certainly unconventional, but it's the best thing we've
>     found so far.
>
>         For example, other IDE's that utilize clang-tidy (e.g. CLion)
>         seem to do so without any visible symlinks.
>
>     Yes, if you're an IDE that already knows how to build the code
>     (has opinions/integrations for the build system) then directly
>     injecting the configuration is feasible. (Clangd has LSP
>     extensions for this). But in VSCode, the build system is just
>     another plugin that may or may not be installed, so a decoupled
>     design seems most likely to work in many configurations.
>
>         To me, that sounds more robust and clean than having to
>         pollute the source tree with symlinks. Of course, that would
>         require some work probably on both of the plugins involved.
>         Also, having a general and flexible approach for this would be
>         nice, as I'm also interested in getting work on a build2
>         extension going, which would require the same functionality.
>
>     Definitely open to new ideas here, but I'm not sure exactly what
>     you're proposing.
>
>     Clangd needs to be able to determine the compile command given a
>     filename, at any time, within the clangd process (i.e. without
>     exchanging LSP messages with the editor).
>
>     Maybe one idea is to stick to compile_commands.json but extend the
>     way they are discovered, e.g. let the Cmake Tools plugin notify
>     Clangd that a certain compile_commands file is relevant and should
>     be considered, even if it's not in an ancestor dir of the source file.
>
>             clangd has to reload the data when appropriate. Today, it
>             caches forever :-( Ilya is working on fixing it!
>
>         I did notice this problem when testing it out yesterday. But I
>         trust that it will get fixed then!
>
>     It's... not trivial. (Other clang tools don't handle this as they
>     tend to be batch)
>     So we'll fix it, but it might take a little time :-)
>
>
>         Cheers,
>         Anton
>
>         On Tue, 27 Nov 2018 at 20:25, Sam McCall <sammccall at google.com
>         <mailto:sammccall at google.com>> wrote:
>
>             On Tue, Nov 27, 2018 at 8:09 PM Anton Södergren via
>             clangd-dev <clangd-dev at lists.llvm.org
>             <mailto:clangd-dev at lists.llvm.org>> wrote:
>
>                 Hello! I'm not sure if this is the best place to ask,
>                 but it's better to get a discussion going rather than
>                 just being confused.
>
>             Right place! Welcome :-)
>
>                 I tried using Clangd in Visual Studio Code, but
>                 noticed that it doesn't integrate well with the CMake
>                 Tools extension, which makes it hard to use together
>                 with a CMake workflow. I would like a way for Clangd
>                 to automatically get the correct info when CMake runs
>                 in the editor.
>                 Specifically, I want seamless and automatic
>                 integration between these two extensions without the
>                 user having to do any additional config:
>
>                   * vscode-clangd
>                     (https://marketplace.visualstudio.com/items?itemName=llvm-vs-code-extensions.vscode-clangd)
>                   * CMake Tools
>                     (https://marketplace.visualstudio.com/items?itemName=vector-of-bool.cmake-tools)
>
>             I'm not familiar with CMake Tools, I guess it helps with
>             editing CMakeLists, CMake configs, and running
>             configure/generate?
>             (Sorry, I would dig into it, about to head out on vacation)
>
>                 I see three possible approaches for this:
>
>                  1. Work with the author of CMake Tools to make the
>                     extension generate the appropriate info for
>                     vscode-clangd
>                  2. Make vscode-clangd retrieve the info from CMake
>                     Tools somehow
>                  3. Create a new extension that acts as a bridge
>                     between the two
>
>                 Or alternatively, some combination of the different
>                 approaches.
>                 I know that the CMake Tools extension integrates well
>                 with Microsoft's C/C++ extension, so maybe it would be
>                 a good idea to do this in a similar way that they did
>                 it. If my understanding is correct, a separate bridge
>                 extension was previously used for this, but I think
>                 they now use a combination of something similar to
>                 approach 1 and 2 for the extensions to communicate
>                 with each other.
>                 I would be interested to hear what you all think would
>                 be the best way to go about this, and maybe I can get
>                 in touch with vector-of-bools (the author of the CMake
>                 Tools extension) about it too.
>
>                 Another question I had regarding this: how does Clangd
>                 find the correct include paths and other info in the
>                 first place? Does it use some kind of compilation
>                 commands file for this? Is it possible to tell Clangd
>                 where to look for such a file? I couldn't really find
>                 any documentation about this when I looked around.
>
>             So if my understanding of CMake Tools is correct, these
>             questions are very much related :-)
>
>             Clangd works like other clang-based tools. Starting at the
>             source file in question, it walks up directories until it
>             finds compile_commands.json
>             <https://clang.llvm.org/docs/JSONCompilationDatabase.html>.
>             This lists the flags required to compile each file in its
>             scope.
>
>             So I think there are three relevant parts here:
>
>               * this file has to be created somehow. CMake can do
>                 this, it's controlled by CMAKE_EXPORT_COMPILE_COMMANDS
>                 <https://cmake.org/cmake/help/v3.5/variable/CMAKE_EXPORT_COMPILE_COMMANDS.html>,
>                 which I believe is on by default now. It writes the
>                 files into the root of the build tree.
>               * the file has to be discovered somehow (if the CMake
>                 build tree != the source tree). The current
>                 best-practice is to manually create a symlink
>                 src/compile_commands.json ->
>                 build/compile_commands.json. I think symlinking
>                 src/.build to build/ is a slightly more principled
>                 approach, but something still has to create a symlink.
>                 (Maybe we could get CMake or CMake Tools to do it?).
>                 Or maybe there's some other clever way to find the
>                 build tree.
>               * clangd has to reload the data when appropriate. Today,
>                 it caches forever :-( Ilya is working on fixing it!
>
>             Gotta run, hope this helps!
>             Patches and ideas welcome :-)
>
>
> _______________________________________________
> clangd-dev mailing list
> clangd-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/clangd-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/clangd-dev/attachments/20181129/fab79298/attachment-0001.html>


More information about the clangd-dev mailing list