# `Mix.Task.Compiler`
[🔗](https://github.com/elixir-lang/elixir/blob/7ff272706afc522e74121493b7166719985cb099/lib/mix/lib/mix/task.compiler.ex#L5)

This module defines the behaviour for a Mix task that does compilation.

A Mix compiler task can be defined by simply using `Mix.Task.Compiler`
in a module whose name starts with `Mix.Tasks.Compile.` and defining
the [`run/1`](`c:run/1`) function:

    defmodule Mix.Tasks.Compile.MyLanguage do
      use Mix.Task.Compiler

      def run(_args) do
        :ok
      end
    end

The [`run/1`](`c:run/1`) function returns an atom indicating the status of the
compilation, and optionally can also return a list of "diagnostics"
such as warnings or compilation errors. Doing this enables code
editors to display issues inline without having to analyze the
command-line output.

If the compiler uses manifest files to track stale sources, it should
define `manifests/0`, and if it writes any output to disk it should
also define `clean/0`.

A compiler supports the same attributes for configuration and
documentation as a regular Mix task. See `Mix.Task` for more information.

## Listening to compilation

When running a long-lived Mix task you may want to detect compilations
triggered in a separate OS process, for example, to reload the modules.
In order to do that, the Mix project may configure listeners:

    def project do
      [
        ...,
        listeners: [SomeDep.MixListener]
      ]
    end

or

    config :mix, :listeners, [SomeDep.MixListener]

Each entry in the list must be either `t:Supervisor.module_spec/0` or
`t:Supervisor.child_spec/0`. Additionally, the listener module must
be defined in a dependency of the project, not the project itself.

The listener process receives the following messages:

  * `{:modules_compiled, info}` - delivered after a set of modules is
    compiled. `info` is a map with the following keys:

      * `:app` - app which modules have been compiled.

      * `:scm` - the SCM module of the compiled project.

      * `:modules_diff` - information about the compiled modules. The
        value is a map with keys: `:added`, `:changed`, `:removed`,
        where each holds a list of modules. There is also a `:timestamp`
        key, which matches the modification time of all the compiled
        module files.

      * `:os_pid` - the operating system PID of the process that run
        the compilation. The value is a string and it can be compared
        with `System.pid/0` to determine if compilation happened in
        the same OS process as the listener.

  * `{:dep_compiled, info}` - delivered after a dependency is compiled.
    `info` is a map with the following keys:

      * `:app` - the dependency app.

      * `:scm` - the SCM module of the dependency.

      * `:manager` - the dependency project management, possible values:
        `:rebar3`, `:mix`, `:make`, `nil`.

      * `:os_pid` - the operating system PID of the process that run
        the compilation. The value is a string and it can be compared
        with `System.pid/0` to determine if compilation happened in
        the same OS process as the listener.

New messages may be added in the future, so the process should have
a catch-all clause and ignore other messages.

Note that the listener starts before any of the project apps are started.

# `status`

```elixir
@type status() :: :ok | :noop | :error
```

# `clean`
*optional* 

```elixir
@callback clean() :: any()
```

Removes build artifacts and manifests.

# `diagnostics`
*optional* 

```elixir
@callback diagnostics() :: [Mix.Task.Compiler.Diagnostic.t()]
```

Lists persisted diagnostics from the compiler.

# `manifests`
*optional* 

```elixir
@callback manifests() :: [Path.t()]
```

Lists manifest files for the compiler.

# `run`

```elixir
@callback run([binary()]) :: status() | {status(), [Mix.Task.Compiler.Diagnostic.t()]}
```

Receives command-line arguments and performs compilation. If it
produces errors, warnings, or any other diagnostic information,
it should return a tuple with the status and a list of diagnostics.

# `after_compiler`
*since 1.10.0* 

```elixir
@spec after_compiler(atom(), ({status(), [Mix.Task.Compiler.Diagnostic.t()]} -&gt;
                          {status(), [Mix.Task.Compiler.Diagnostic.t()]})) ::
  :ok
```

Adds a callback that runs after a given compiler.

The callback is invoked after the compiler runs and
it receives a tuple with current status and the list
of diagnostic. It must return the updated status and
diagnostics.

If the given compiler does not run (for instance,
because an earlier compiler in the stack has aborted),
the callback will not be executed.

# `compilers`

Returns all compilers for the current project.

# `diagnostics`

Lists persisted diagnostics from all compilers in the current project.

# `manifests`

Lists manifest files for all compilers in the current project.

# `reenable`
*since 1.19.0* 

```elixir
@spec reenable(compilers) :: :ok when compilers: :all | [atom()]
```

Reenables given compilers so they can be executed again down the stack.

If an umbrella project reenables compilers, they are re-enabled for all
child projects.

Default is `:all` which effectively means all the compilers returned by
`Mix.Task.Compiler.compilers()` are to be reenabled. This task always
re-enables `"compile"` and `"compile.all"`.

# `run`
*since 1.19.0* 

Runs the given list of compilers with the given arguments.

It returns a `{status, diagnostics}` tuple. If a compiler
errors, following compilers do not run.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
