[cmake-developers] daemon-mode meeting last Tuesday
Stephen Kelly
steveire at gmail.com
Tue Jun 28 18:41:49 EDT 2016
Tobias Hunger wrote:
> Hello CMake Developers,
>
> Stephen Kelly and me met last Tuesday to talk about the daemon-mode patch
> we both have been working on. It was a very productive meeting: We managed
> to resolve almost all the differences of opinion we had.
Thanks Tobias for the summary and everyone else for the discussion.
Here are a few additional notes that I took when meeting Tobias last week.
These notes don't change anything in the discussion, but expands on a few
things to put some meat on the bones and lists some discarded design
options.
cmMessenger
-----------
> * Having cmMessanger would be nice and will make things easier.
In particular - a cmMessenger class can have some virtual methods
implemented to print to the console as cmake::IssueMessage currently does.
It would be inherited by a cmServerMessenger which would override the
virtual methods to send them over the server IPC protocol instead of
printing them on stdout. This has the advantage of not losing semantic
information - a backtrace becomes a JSON array, meaning clients don't have
to try to parse the backtrace out of the stdout message as they currently
do. That becomes possible with just a IssueMessage virtual. See
http://thread.gmane.org/gmane.comp.programming.tools.cmake.devel/15607
Additionally, the cmMessenger can have additional high-level virtual
methods, such as for find_package results making it easier for user tools
and IDEs to get a list of packages searched for and make it possible to give
users use-case specific ways of specifying where packages are.
Similarly it can have a virtual method for try_compile results (somehow -
this might require extending the message type for scripting API) which also
give user tools more opportunities to present the user with semantic
information and not discard the intent of the person writing the
buildsystem.
Another place where a virtual method on cmMessenger would make sense is for
policy warnings, giving user tools a chance to present them to the user
without trying to parse them from stdout.
There may be other messages which have semantics whose meaning we currently
discard by printing to stdout.
All of this is currently blocked by a clean-up in the parser needing further
review and perhaps further implementation work:
http://thread.gmane.org/gmane.comp.programming.tools.cmake.devel/15607/focus=16663
Name
----
Last year before publication I was calling this feature a 'metadata server'
(class called cmMetadataServer etc). I probably made a mistake renaming it
to a daemon. Now, 'metadata server' might be better and more specific than
'server' alone.
Change Notification
-------------------
I wrote previously that I think change notification is an essential feature
of the first version of the protocol - otherwise the output is no better
than a static generated file.
http://thread.gmane.org/gmane.comp.programming.tools.cmake.devel/16589/focus=16648
Tobias was concerned that implementing filesystem watching for all necessary
platforms is an unreasonable burden and he would prefer something like
QFileSystemWatcher.
libuv has a portable abstraction for filesystem change notification similar
in a way to QFileSystemWatcher. I implemented a basic use of the libuv API
fs notification API last year.
Action item for me is to dig out that work or do it again. Then the metadata
server can emit a message on the protocol when the source directory content
changes.
Feature Flags
-------------
> 1.2 Protocol versions
>
> * We need the daemon-mode to support different protocol versions.
>
> * We want to have the option to mark protocol versions as experimental.
As far as I know, Chrome has a development model whereby unfinished features
are checked into master immediately and developed there, instead of being
developed in a branch. The new/experimental features are disabled by default
with 'feature flags' so that people/CI can enable and test features which
are candidates to be enabled by default to everyone.
We discussed whether this would make sense for the server instead of
'experimental' protocol versions. We decided that such feature flags would
make sense if there would be many experimental features in flight from
multiple contributors over multiple cmake releases. We don't expect this to
be the case, so we consider feature flags to be over-engineered for the
server for now.
InReplyTo
---------
> * Currently a reply (and error and all other messages in response to a
> request) contain a "inReplyTo" with the type string from the request
> triggering the reply.
>
> Stephen thinks that is not necessary and argues anything that is not
> strictly necessary should not be in the first version of the protocol.
Tobias told me that the only reason for this is to make it easier for people
developing the actual protocol to paste blocks of text which contain
multiple server messages. For example a developer could paste a 'configure'
and a 'compute' and a 'codeModel' message over and over while implementing
the 'codeModel' message. If the 'configure' or 'compute' fail for some
reason with an error Tobias thinks it is confusing to figure out which one
had the error after the fact. I don't agree that that is hard or confusing.
To be clear: The inReplyTo will never be used by client tools. It is only
for the above use-case.
My concern is that if we add something only for a use-case like that, client
tools will start to use it for something it is not designed for. Then we
will regret that we did not design something better for the clients actual
need (because inReplyTo isn't exactly what they actually need).
So, I am strongly in favor of keeping the protocol content to the absolute
minimum - only include things which we know client use-cases for.
Downstreams abusing CMake script APIs for things they were not intended for
is a long term problem for CMake. We should avoid introducing that problem
in the server protocol.
Especially as inReplyTo, even in its current form is 'fuzzy' to me: Is it in
spontaneous messages which are not in response to anything (message()
output, change notifications etc)? Does it have 'special' values?
Initialization Granularity
--------------------------
We talked about what should happen when a client starts the metadata server
and what sequence of protocol commands the client has to send to set things
up properly.
In my implementation, the initial handshake causes the configure step and
the compute step to be executed. The client can't cause only the configure
step to be executed. This means that an out-of-process cmake-gui or other
cache editor:
http://thread.gmane.org/gmane.comp.programming.tools.cmake.devel/16550/focus=16556
using the metadata server would have to do a full handshake instead of
'just' the configure part for example, making it not analogous to the
current cmake-gui.
So, a granular approach allows the use-case of partial initialization while
also making it possible for a client to do 'full initialization' by
requesting the 'configure', 'compute' and 'generate' steps explicitly.
As with the cmake-gui, it might make sense to specify the 'generate' command
as implying the dependee two. We might benefit from some state-machine
diagram telling users (and us) what protocol commands are possible in which
state.
Capabilities
------------
> * Move generators and other static information into a separate cmake
> commandline invocation (http://public.kitware.com/Bug/view.php?id=15462):
Previously Tobias wanted this only as part of the protocol, not as something
that can be emitted with a regular command line request in the same manner
as --help for example.
I think such capabilities information should be available easily to anyone
writing scripts which invoke cmake.
Tobias needs that information for Qt Creator because it needs to know what
generators are available for example. That is determined when Creator is
started each time.
Tobias mentioned that such capability queries should be fast - executing
lots of tools to find out their versions and capabilities is something that
slows down the start up of QtCreator. He reasoned that he should only have
to run one cmake - start the server only - not run cmake first to get the
capabilities, then run it a second time in server mode.
I noted that starting the server just for a query like this is very much
likely to be slower than just getting the information on the command line.
Additionally, the server can be started later when loading a project instead
of when starting QtCreator itself. Tobias was convinced by that.
> TODO: Figure out how to get all the generator information, e.g. which
> values the flags some generator taken can have (architecture, etc.).
> Stephen volunteered to check into this.
This is about toolsets, platforms, architectures which I think can be passed
to cmake when executing it with Visual Studio generators. I'm not very clear
on that stuff. Brad, do you have an overview?
Use-case Driven Design
----------------------
> 2.6) project (Return project structure)
>
> * Rename to "codemodel" to make the use-case for the data more clear.
One of the differences between the protocol proposed by Tobias is that he
has one protocol command which returns a structure of all targets, their
files and the includes, defines and flags of the files. In contrast, I had
implemented an approach which provides multiple protocol commands returning
more-granular structures:
http://thread.gmane.org/gmane.comp.programming.tools.cmake.devel/16589/focus=16640
In the discussion we realized that the two approaches satisfy two different
use-cases. Tobias needs to get all C++ source files and the includes,
defines and flags in order to populate a C++ code model for the project.
That allows things like 'find usages of this symbol in the project' etc.
A granular way of returning this information to the client would be
inconvenient and ineffective.
Whereas the use-case for the structure Tobias wants has a use-case of
populating a C++ code model, my proposed protocol commands for target_info,
file_info etc are for the use-case of understanding the CMake code.
That is why the 'codeModel' in Tobias' proposal does not list include
directories, compile definitions etc of targets, but only of files. The code
model cares about compilations. It is not concerned with targets. The
protocol commands I proposed are for helping the user to understand what the
effect of CMake code like
target_include_directories(MyTarget ${SOME_VAR})
target_compile_definitions(MyTarget ${SOME_OTHER_VAR})
target_link_libraries(MyTarget ${YET_ANOTHER_VAR})
means. The variables (and transitive usage requirements) make the impact of
those lines invisible in the code, as my video demonstrates.
Those kinds of protocol commands and features are in scope for the protocol,
and perhaps also for QtCreator some day, but they are out of scope for now.
As a result of that part of the discussion, I think it might make sense to
try to use 'use-case driven design' when trying to decide what should be in
the protocol.
There may be some element of 'redundancy' occurring in the protocol as a
result. For example, both the 'codeModel' protocol command and the
'target_info' would return 'stuff (including object sources in both cases)
associated with a target'. We don't yet know if that is a problem.
Cache
-----
> 2.7 cache (report contents of CMakeCache.txt file)
>
> * Review by other potential users would be appreciated, but no obvious
> problems seen.
We thought this would be useful for the work of Daniel on his cache-editor
tool, and so feedback from him and Clinton (as cmake-gui is potentially
another user of this stuff) would be valued.
Other Movers
------------
Microsoft just published a JSON protocol for language servers to get
information into VSCode, and for other user tools to do the same.
https://www.reddit.com/r/programming/comments/4qad14
This could be interesting to learn from. Although they say the protocol is
JSON, I can only seem to find TypeScript protocol stuff. Presumably that
gets translated to JSON for wire communication, but that's not clear from
their docs.
https://github.com/google/xi-editor
is another editor based on a JSON protocol with a language server.
Neovim too:
https://github.com/neovim/neovim/wiki/Plugin-UI-architecture
These and other examples indicate that user tools are moving towards multi-
process with some defined protocols. I don't think the generic protocol from
Microsoft is a replacement for the cmake metadata server protocol, but there
are certainly going to be lessons to learn from there.
C++11
-----
One central difference between the cmake metadata server code and the rest
of CMake is that I used cxx_auto_type and cxx_range_for extensively for my
sanity and productivity.
I don't see any problem with requiring CMake to be built with a recent
compiler in order to conditionally support server mode. QtCreator also
requires some C++11 features and it is likely the first user of the protocol
and the only major one for some time.
Thanks,
Steve.
More information about the cmake-developers
mailing list