This is an archive of the discontinued LLVM Phabricator instance.

[clangd] DO NOT SUBMIT. Draft interfaces for build system integration.
Needs ReviewPublic

Authored by ilya-biryukov on Nov 27 2018, 8:20 AM.

Details

Reviewers
klimek
sammccall
Summary

A proposal for the interface of the new build system integration.
Similar to CompilationDatabase, but will provide more functionality and live
in clangd instead of tooling until stabilized.

Main points of interest are:

  • clangd::Integration is a user-facing API, it handles loading the proper build system integrations from the directory structure and notifying the clients about all changes. It implements clang::GlobalCompilationDatabase and is used by all of clangd to get compile commands, etc.
  • clangd::BuildSystem interface is for build system implementations. It handles interactions with a single build system (initially only 'compile_commands.json', but we also plan to experiment with adding direct CMake or ninja support).
  • The clangd::GlobalCompilationDatabase now also provides a VFS instance alongside the compile command. The idea is to allow build systems to overlay generated files, if they can need (this is Bazel-specific AFAIK). It is also the responsibility of the buildsystem to update any dependencies (e.g. the generated files) it knows about before providing the compile commands.

Event Timeline

ilya-biryukov created this revision.Nov 27 2018, 8:20 AM
klimek added inline comments.Nov 28 2018, 2:28 AM
clangd/BuildSystem.h
29

'Integration' is a bit of a weird name, as it doesn't tell me what it does.
What I'd have expected is an abstraction like 'Workspace' (which I believe is a domain term in IDEs) that would:
-> be in some form coupled to 1 build system
-> provide a file system view on the workspace
-> provide the ability to watch for changed files

Then the BuildSystem would:
-> provide the ability to watch for changed inputs / commands
-> provide the ability to "prepare all inputs"
-> potentially provide the ability to get a build graph

If Integration wants to be that, it should:

  • not extend GlobalCompilationDatabase
  • not have getCompileCommand itself
clangd/BuildSystemPlugin.h
31

Do you actually foresee more than 1 being available in a single workspace? Feels a bit premature generalization to me :)

ilya-biryukov marked an inline comment as done.Nov 28 2018, 5:54 AM

Thanks for taking a look and sorry for the confusion with naming. I should've renamed Integration before sending this patch.

clangd/BuildSystem.h
29

'Integration' is a bit of a weird name, as it doesn't tell me what it does.

It is, sorry about that. This is not final. I intended to put this into the 'buildsystem' namespace, so it'd be used as 'buildsystem::Integration', which would make more sense.

What I'd have expected is an abstraction like 'Workspace' (which I believe is a domain term in IDEs) that would:
-> be in some form coupled to 1 build system
-> provide a file system view on the workspace
-> provide the ability to watch for changed files

The abstraction you're looking for is called BuildSystem in this patch.
It is decoupled from watching for files (this is handled by FileSystemProvider), it can watch files internally but tells the users about the changes in terms of source files that had their inputs changed.

Then the BuildSystem would:
-> provide the ability to watch for changed inputs / commands
-> provide the ability to "prepare all inputs"

This is exactly what BuildSystem does.

-> potentially provide the ability to get a build graph

I was thinking about this as well, but still not sure if this information is better inferred by clangd when running the compiler, so decided to leave it out until we have a use-case for that.

If Integration wants to be that, it should:
not extend GlobalCompilationDatabase
not have getCompileCommand itself

There is a discrepancy between the needs of the build system implementations and what clangd has at the protocol level.

  • At the protocol level, clangd operates on the files and it needs to provide features on a per-file manner: get diagnostics for a file, run code completion in a file, format a file, etc.
  • At the build system implementation level, we care about different things: discovering which build system is used, watching for changes to important files (BUILD, CMakeLists.txt, compiler_commands.json, etc.), reporting those changes to the build system users, building the generated files, providing compile commands, adding build depenndecies, etc.

buildsystem::Integration serves as a layer that ties those two together and provides an interface that higher layers of clangd are more comfortable with, e.g. a file-based interface that GlobalCompilatioDatabase provides.

My initial goal was to replace the GlobalCompilationDatabase with Integration and make it a non-abstract class, making it clear it just wraps build system integration into a form that's a bit more convenient for clangd uses. This turned out to be some work (we have OverlayCDB and test compilation databases that rely on this interface, so it's some work and it's not clear if that would make the code simpler at the end, so I decided to postpone it for now.

clangd/BuildSystemPlugin.h
31

It's not a problem with compile_commands.json, but I foresee that being a problem if we start supporting the actual build systems like cmake and bazel. Sadly it's not uncommon for a C++ project to have multiple build systems (in a transition phase, to support more platforms, etc).

klimek added inline comments.Nov 29 2018, 6:32 AM
clangd/BuildSystem.h
29

So, I would still vote for separating a Workspace from a BuildSystem, as I'd expect a Workspace over time to grow VCS capabilities, and I'd expect having one abstractions that covers both builds and VCSs confusing.

I now understand the "Integration" layer better, but it still looks like it's doing too many things:
specificially, it seems like it's basically at the same time a single view of all build systems / workspaces AND the thing that manages them - and I'd definitely split that up; that is, both of these are useful but they should be different classes.

ilya-biryukov added inline comments.Nov 30 2018, 9:42 AM
clangd/BuildSystem.h
29

So, I would still vote for separating a Workspace from a BuildSystem, as I'd expect a Workspace over time to grow VCS capabilities, and I'd expect having one abstractions that covers both builds and VCSs confusing.

That makes sense to me too, but I don't have the full understanding of the VCS capabilities we might want to have. Something that popped up before in various discussions was tracking a changing VCS branch to keep separate versions of the index to hotswap. Will have to think more about it, thanks for the input.

specificially, it seems like it's basically at the same time a single view of all build systems / workspaces AND the thing that manages them - and I'd definitely split that up; that is, both of these are useful but they should be different classes.

That makes total sense, the implementation is actually split even though it's not visible in this patch: the private Discovery class handles the loading of the build system tree, etc.