=======================
Parseable Driver Output
=======================

.. contents::
   :local:

Introduction
============

This document serves to describe the parseable output format provided by the
Swift compiler driver with the "-parseable-output" flag. This output format is
intended to be parsed by other programs; one such use case is to allow an IDE to
construct a detailed log based on the commands the driver issued.

Message Format
==============

The parseable output provided by the Swift driver is provided as messages
encoded in JSON objects. All messages are structured like this::

   <Message Length>\n
   {
     "kind": "<Message Kind>",
     "name": "<Message Name>",
     "<key>": "<value>",
     ...
   }\n

This allows the driver to pass as much information as it wants about the ongoing
compilation, and programs which parse this data can decide what to use and what
to ignore.

Message Kinds
=============

.. contents::
   :local:

The driver may emit four kinds of messages: "began", "finished", "signalled",
and "skipped".

Began Message
-------------

A "began" message indicates that a new task began. As with all task-based
messages, it will include the task's PID under the "pid" key. It may specify the
task's inputs as an array of paths under the "inputs" key. It may specify the
task's outputs as an array of objects under the "outputs" key. An "outputs"
object will have two fields, a "kind" describing the type of the output, and a
"path" containing the path to the output. A "began" message will specify the
command which was executed under the "command" key.

Example::

   {
     "kind": "began",
     "name": "compile",
     "pid": 12345,
     "inputs": [ "/src/foo.swift" ],
     "outputs": [
        {
          "type": "object",
          "path": "/build/foo.o"
        },
        {
          "type": "swiftmodule",
          "path": "/build/foo.swiftmodule"
        },
        {
          "type": "diagnostics",
          "path": "/build/foo.dia"
        },
     ],
     "command": "swift -frontend -c -primary-file /src/foo.swift /src/bar.swift -emit-module-path /build/foo.swiftmodule -emit-diagnostics-path /build/foo.dia"
   }

Finished Message
----------------

A "finished" message indicates that a task finished execution. As with all task-
based messages, it will include the task's PID under the "pid" key. It will
include the exit status of the task under the "exit-status" key. It may include
the stdout/stderr of the task under the "output" key; if this key is missing,
no output was generated by the task.

Example::

   {
     "kind": "finished",
     "name": "compile",
     "pid": 12345,
     "exit-status": 0
     // "output" key omitted because there was no stdout/stderr.
   }

Signalled Message
-----------------

A "signalled" message indicates that a task exited abnormally due to a signal.
As with all task-based message, it will include the task's PID under the "pid"
key. It may include an error message describing the signal under the
"error-message" key. As with the "finished" message, it may include the
stdout/stderr of the task under the "output" key; if this key is missing, no
output was generated by the task.

Example::

   {
     "kind": "signalled",
     "name": "compile",
     "pid": 12345,
     "error-message": "Segmentation fault: 11"
     // "output" key omitted because there was no stdout/stderr.
   }

Skipped Message
---------------

A "skipped" message indicates that the driver determined a command did not need to
run during the current compilation. A "skipped" message is equivalent to a "began"
message, with the exception that it does not include the "pid" key.

Example::

   {
     "kind": "skipped",
     "name": "compile",
     "inputs": [ "/src/foo.swift" ],
     "outputs": [
        {
          "type": "object",
          "path": "/build/foo.o"
        },
        {
          "type": "swiftmodule",
          "path": "/build/foo.swiftmodule"
        },
        {
          "type": "diagnostics",
          "path": "/build/foo.dia"
        },
     ],
     "command": "swift -frontend -c -primary-file /src/foo.swift /src/bar.swift -emit-module-path /build/foo.swiftmodule -emit-diagnostics-path /build/foo.dia"
   }

Message Names
=============

The name of the message identifies the kind of command the message describes.
Some valid values are:

   - compile
   - merge-module
   - link
   - generate-dsym

A "compile" message represents a regular Swift frontend command.
A "merge-module" message represents an invocation of the Swift frontend which is
used to merge partial swiftmodule files into a complete swiftmodule. A "link"
message indicates that the driver is invoking the linker to produce an
executable or a library. A "generate-dsym" message indicates that the driver is
invoking dsymutil to generate a dSYM.

Parsers of this format should be resilient in the event of an unknown name, as
the driver may emit messages with new names whenever it needs to execute a new
kind of command.