# `Mix.Project`
[🔗](https://github.com/elixir-lang/elixir/blob/55da97b9a329638ed5dfdbb1f8e10c9895829655/lib/mix/lib/mix/project.ex#L5)

Defines and manipulates Mix projects.

A Mix project is defined by calling `use Mix.Project` in a module, usually
placed in `mix.exs`:

    defmodule MyApp.MixProject do
      use Mix.Project

      def project do
        [
          app: :my_app,
          version: "1.0.0"
        ]
      end
    end

> #### `use Mix.Project` {: .info}
>
> When you `use Mix.Project`, it notifies Mix that a new project
> has been defined, so all Mix tasks use your module as a starting
> point.

## Configuration

In order to configure Mix, the module that calls `use Mix.Project` should export
a `project/0` function that returns a keyword list representing configuration
for the project.

This configuration can be read using `Mix.Project.config/0`. Note that
`config/0` won't fail if a project is not defined; this allows many Mix tasks
to work without a project.

If a task requires a project to be defined or needs to access a
special function within the project, the task can call `Mix.Project.get!/0`
which fails with `Mix.NoProjectError` in the case a project is not
defined.

There isn't a comprehensive list of all the options that can be returned by
`project/0` since many Mix tasks define their own options that they read from
this configuration. For example, look at the "Configuration" section in the
documentation for the `Mix.Tasks.Compile` task.

These are a few options that are not used by just one Mix task (and will thus
be documented here):

  * `:build_per_environment` - if `true`, builds will be *per-environment*. If
    `false`, builds will go in `_build/shared` regardless of the Mix
    environment. Defaults to `true`.

  * `:aliases` - a list of task aliases. For more information, check out the
    "Aliases" section in the documentation for the `Mix` module. Defaults to
    `[]`.

  * `:config_path` - a string representing the path of the main config
    file. See `config_files/0` for more information. Defaults to
    `"config/config.exs"`.

  * `:deps` - a list of dependencies of this project. Refer to the
    documentation for the `Mix.Tasks.Deps` task for more information. Defaults
    to `[]`.

  * `:deps_path` - directory where dependencies are stored. Also see
    `deps_path/1`. Defaults to `"deps"`.

  * `:lockfile` - the name of the lockfile used by the `mix deps.*` family of
    tasks. Defaults to `"mix.lock"`.

Mix tasks may require their own configuration inside `def project`. For example,
check the `Mix.Tasks.Compile` task and all the specific compiler tasks
(such as `Mix.Tasks.Compile.Elixir` or `Mix.Tasks.Compile.Erlang`).

Note that different tasks may share the same configuration option. For example,
the `:erlc_paths` configuration is used by `mix compile.erlang`, `mix compile.yecc`,
and other tasks.

> #### Keep `project/0` fast {: .warning}
>
> `project/0` is called whenever your `mix.exs` is loaded, so heavy
> computation should be avoided. If a task requires a potentially complex
> configuration value, it should allow its configuration to be set to an
> anonymous function or similar, so that it can be invoked only when
> needed by the task itself.

## CLI configuration

Mix is most often invoked from the command line. For this purpose, you may define
a specific `cli/0` function which customizes default values when executed from
the CLI. For example:

    def cli do
      [
        default_task: "phx.server",
        preferred_envs: [docs: :docs]
      ]
    end

The example above sets the default task (used by `iex -S mix` and `mix`) to
`phx.server`. It also sets the default environment for the "mix docs" task to
be "docs".

The following CLI configuration are available:

  * `:default_env` - the default environment to use when none is given
    and `MIX_ENV` is not set

  * `:default_target` - the default target to use when none is given
    and `MIX_TARGET` is not set

  * `:default_task` - the default task to invoke when none is given

  * `:preferred_envs` - a keyword list of `{task, env}` tuples where `task`
    is the task name as an atom (for example, `:"deps.get"`) and `env` is the
    preferred environment (for example, `:test`)

  * `:preferred_targets` - a keyword list of `{task, target}` tuples where
    `task` is the task name as an atom (for example, `:test`) and `target`
    is the preferred target (for example, `:host`)

## Erlang projects

Mix can be used to manage Erlang projects that don't have any Elixir code. To
ensure Mix tasks work correctly for an Erlang project, `language: :erlang` has
to be part of the configuration returned by `project/0`. This setting also
makes sure Elixir is not added as a dependency to the generated `.app` file or
to the escript generated with `mix escript.build`, and so on.

## Umbrella projects

Umbrella projects are a convenience to help you organize and manage multiple
applications. While it provides a degree of separation between applications,
those applications are not fully decoupled, as they share the same configuration
and the same dependencies.

In an umbrella project, you have an `apps/` folder where you store each application.
Then, instead of each app in the umbrella having its own configuration, build cache,
lockfile and so, they all point to the parent project by specifying the following
configuration in their `mix.exs`:

    build_path: "../../_build",
    config_path: "../../config/config.exs",
    deps_path: "../../deps",
    lockfile: "../../mix.lock",

The pattern of keeping multiple applications in the same repository is known as
[monorepo](https://en.wikipedia.org/wiki/Monorepo). Umbrella projects maximize
this pattern by providing conveniences to compile, test and run multiple
applications at once. When an umbrella application needs to depend on another
one, it can be done by passing the `in_umbrella: true` option to your dependency.
If an umbrella application `:foo` depends on its sibling `:bar`, you can specify
this dependency in `foo`'s `mix.exs` file as:

    {:bar, in_umbrella: true}

### Undoing umbrellas

Using umbrella projects can impact how you design and write your software and,
as time passes, they may turn out to be the wrong choice.
If you find yourself in a position where you want to use different configurations
in each application for the same dependency or use different dependency versions,
then it is likely your codebase has grown beyond what umbrellas can provide.

If you find yourself in this situation, you have two options:

  1. Convert everything into a single Mix project, which can be done in steps.
     First move all files in `lib`, `test`, `priv`, and friends into a single
     application, while still keeping the overall umbrella structure and
     `mix.exs` files. For example, if your umbrellas has three applications,
     `foo`, `bar` and `baz`, where `baz` depends on both `foo` and `bar`,
     move all source to `baz`. Then remove `foo` and `bar` one by one,
     updating any configuration and removing references to the `:foo` and
    `:bar` application names. Until you have only a single application.

  2. Remove umbrella structure while keeping them as distinct applications.
     This is done by moving applications outside of the umbrella
     project's `apps/` directory and updating the projects' `mix.exs` files
     to no longer set the `build_path`, `config_path`, `deps_path`, and
     `lockfile` configurations, guaranteeing each of them have their own
     build and dependency structure.

Keep in mind that umbrellas are one of many options for managing private
packages within your organization. You might:

  1. Have multiple directories inside the same repository and using `:path`
     dependencies (which is essentially the monorepo pattern)
  2. Use private Git repositories and Mix' ability to fetch Git dependencies
  3. Publishing packages to a private [Hex.pm](https://hex.pm/) organization

## Invoking this module

This module contains many functions that return project information and
metadata. However, since Mix is not included nor configured during releases,
we recommend using the functions in this module only inside Mix tasks.
If you need to configure your own app, consider using the application
environment instead. For example, don't do this:

    def some_config do
      Mix.Project.config()[:some_config]
    end

Nor this:

    @some_config Mix.Project.config()[:some_config]

Instead, do this:

    def some_config do
      Application.get_env(:my_app, :some_config)
    end

Or this:

    @some_config Application.compile_env(:my_app, :some_config)

# `build_structure_opts`

```elixir
@type build_structure_opts() :: [symlink_ebin: boolean(), source: String.t()]
```

# `deps_traversal_opts`

```elixir
@type deps_traversal_opts() :: [depth: pos_integer(), parents: [atom()]]
```

Options for dependency traversal functions.

These options control how dependency trees are traversed and filtered
in functions like `deps_scms/1`, `deps_paths/1`, and `deps_tree/1`.

# `app_path`

```elixir
@spec app_path(keyword()) :: Path.t()
```

Returns the application path inside the build.

The returned path will be expanded.

## Examples

If your project defines the app `my_app`:

    Mix.Project.app_path()
    #=> "/path/to/project/_build/shared/lib/my_app"

# `apps_paths`
*since 1.4.0* 

```elixir
@spec apps_paths(keyword()) :: %{optional(atom()) =&gt; Path.t()} | nil
```

Returns a map with the umbrella child applications paths.

These paths are based on the `:apps_path` and `:apps` configurations.

If the given project configuration identifies an umbrella project, the return
value is a map of `app => path` where `app` is a child app of the umbrella and
`path` is its path relative to the root of the umbrella project.

If the given project configuration does not identify an umbrella project,
`nil` is returned.

## Examples

    Mix.Project.apps_paths()
    #=> %{my_app1: "apps/my_app1", my_app2: "apps/my_app2"}

# `build_path`

```elixir
@spec build_path(keyword()) :: Path.t()
```

Returns the build path for the given project.

The build path is built based on the `:build_path` configuration
(which defaults to `"_build"`) and a subdirectory. The subdirectory
is built based on two factors:

  * If `:build_per_environment` is set (the default), the subdirectory
    is the value of `Mix.env/0` (which can be set via `MIX_ENV`).
    Otherwise it is set to "shared".

  * If `Mix.target/0` is set (often via the `MIX_TARGET` environment
    variable), it will be used as a prefix to the subdirectory.

The behaviour of this function can be modified by two environment
variables, `MIX_BUILD_ROOT` and `MIX_BUILD_PATH`, see [the Mix
documentation for more information](Mix.html#environment-variables).

> #### Naming differences {: .info}
>
> Ideally the configuration option `:build_path` would be called
> `:build_root`, as it only sets the root component of the build
> path but not the subdirectory. However, its name is preserved
> for backwards compatibility.

## Examples

    Mix.Project.build_path()
    #=> "/path/to/project/_build/shared"

If `:build_per_environment` is set to `true`, it will create a new build per
environment:

    Mix.env()
    #=> :dev
    Mix.Project.build_path()
    #=> "/path/to/project/_build/dev"

# `build_structure`

```elixir
@spec build_structure(
  keyword(),
  build_structure_opts()
) :: :ok
```

Builds the project structure for the given application.

## Options

  * `:symlink_ebin` - symlink ebin instead of copying it

  * `:source` - the source directory to copy from.
    Defaults to the current working directory.

# `clear_deps_cache`
*since 1.7.0* 

```elixir
@spec clear_deps_cache() :: :ok
```

Clears the dependency for the current environment.

Useful when dependencies need to be reloaded due to change of global state.

For example, Nerves uses this function to force all dependencies to be
reloaded after it updates the system environment. It goes roughly like
this:

  1. Nerves fetches all dependencies and looks for the system specific deps
  2. Once the system specific dep is found, it loads it alongside env vars
  3. Nerves then clears the cache, forcing dependencies to be loaded again
  4. Dependencies are loaded again, now with an updated env environment

# `compile_path`

```elixir
@spec compile_path(keyword()) :: Path.t()
```

Returns the paths the given project compiles to.

If no configuration is given, the one for the current project will be used.

The returned path will be expanded.

## Examples

If your project defines the app `my_app`:

    Mix.Project.compile_path()
    #=> "/path/to/project/_build/dev/lib/my_app/ebin"

# `config`

```elixir
@spec config() :: keyword()
```

Returns the project configuration.

If there is no project defined, it still returns a keyword
list with default values. This allows many Mix tasks to work
without the need for an underlying project.

Note this configuration is cached once the project is
pushed onto the stack. Calling it multiple times won't
cause it to be recomputed.

Do not use `Mix.Project.config/0` to find the runtime configuration.
Use it only to configure aspects of your project (like
compilation directories) and not your application runtime.

# `config_files`

```elixir
@spec config_files() :: [Path.t()]
```

Returns a list of project configuration files for this project.

This function is usually used in compilation tasks to trigger
a full recompilation whenever such configuration files change.

It returns the lock manifest, and all config files in the `config`
directory that do not start with a leading period (for example,
`.my_config.exs`).

Note: before Elixir v1.13.0, the `mix.exs` file was also included
as a config file, but since then it has been moved to its own
function called `project_file/0`.

# `config_mtime`
*since 1.7.0* 

```elixir
@spec config_mtime() :: posix_mtime when posix_mtime: integer()
```

Returns the latest modification time from config files.

This function is usually used in compilation tasks to trigger
a full recompilation whenever such configuration files change.
For this reason, the mtime is cached to avoid file system lookups.

However, for effective used of this function, you must avoid
comparing source files with the `config_mtime` itself. Instead,
store the previous `config_mtime` and compare it with the new
`config_mtime` in order to detect if something is stale.

Note: before Elixir v1.13.0, the `mix.exs` file was also included
in the mtimes, but not anymore. You can compute its modification
date by calling `project_file/0`.

# `consolidation_path`

```elixir
@spec consolidation_path(keyword()) :: Path.t()
```

Returns the path where protocol consolidations are stored.

The returned path will be expanded.

## Examples

If your project defines the app `my_app`:

    Mix.Project.consolidation_path()
    #=> "/path/to/project/_build/dev/lib/my_app/consolidated"

Inside umbrellas:

    Mix.Project.consolidation_path()
    #=> "/path/to/project/_build/dev/consolidated"

# `deps_apps`
*since 1.11.0* 

```elixir
@spec deps_apps() :: [atom()]
```

Returns all dependencies app names.

The order they are returned is guaranteed to be sorted
for proper dependency resolution. For example, if A
depends on B, then B will listed before A.

# `deps_path`

```elixir
@spec deps_path(keyword()) :: Path.t()
```

Returns the path where dependencies are stored for the given project.

If no configuration is given, the one for the current project is used.

The returned path will be expanded.

## Examples

    Mix.Project.deps_path()
    #=> "/path/to/project/deps"

# `deps_paths`

```elixir
@spec deps_paths(deps_traversal_opts()) :: %{optional(atom()) =&gt; Path.t()}
```

Returns the full path of all dependencies as a map.

## Options

  * `:depth` - only returns dependencies to the depth level,
    a depth of `1` will only return top-level dependencies
  * `:parents` - starts the dependency traversal from the
    given parents instead of the application root

## Examples

    Mix.Project.deps_paths()
    #=> %{foo: "deps/foo", bar: "custom/path/dep"}

# `deps_scms`
*since 1.10.0* 

```elixir
@spec deps_scms(deps_traversal_opts()) :: %{optional(atom()) =&gt; Mix.SCM.t()}
```

Returns the SCMs of all dependencies as a map.

See `Mix.SCM` module documentation to learn more about SCMs.

## Options

  * `:depth` - only returns dependencies to the depth level,
    a depth of `1` will only return top-level dependencies
  * `:parents` - starts the dependency traversal from the
    given parents instead of the application root

## Examples

    Mix.Project.deps_scms()
    #=> %{foo: Mix.SCM.Path, bar: Mix.SCM.Git}

# `deps_tree`
*since 1.15.0* 

```elixir
@spec deps_tree(deps_traversal_opts()) :: %{optional(atom()) =&gt; [atom()]}
```

Returns the dependencies of all dependencies as a map.

## Options

  * `:depth` - only returns dependencies to the depth level,
    a depth of `1` will only return top-level dependencies
  * `:parents` - starts the dependency traversal from the
    given parents instead of the application root

## Examples

    Mix.Project.deps_tree()
    #=> %{foo: [:bar, :baz], bar: [], baz: []}

# `ensure_structure`

```elixir
@spec ensure_structure(
  keyword(),
  build_structure_opts()
) :: :ok
```

Ensures the project structure for the given project exists.

In case it does exist, it is a no-op. Otherwise, it is built.

`opts` are the same options that can be passed to `build_structure/2`.

# `get`

```elixir
@spec get() :: module() | nil
```

Retrieves the current project if there is one.

If there is no current project, `nil` is returned. This
may happen in cases there is no `mix.exs` in the current
directory.

If you expect a project to be defined, i.e., it is a
requirement of the current task, you should call
`get!/0` instead.

# `get!`

```elixir
@spec get!() :: module()
```

Same as `get/0`, but raises an exception if there is no current project.

This is usually called by tasks that need additional
functions on the project to be defined. Since such
tasks usually depend on a project being defined, this
function raises a `Mix.NoProjectError` exception in
case no project is available.

# `in_project`

```elixir
@spec in_project(atom(), Path.t(), keyword(), (module() -&gt; result)) :: result
when result: term()
```

Runs the given `fun` inside the given project.

This function changes the current working directory and
loads the project at the given directory onto the project
stack.

A `post_config` can be passed that will be merged into
the project configuration.

`fun` is called with the module name of the given `Mix.Project`.
The return value of this function is the return value of `fun`.

## Examples

    Mix.Project.in_project(:my_app, "/path/to/my_app", fn module ->
      "Mix project is: #{inspect(module)}"
    end)
    #=> "Mix project is: MyApp.MixProject"

# `load_paths`

> This function is deprecated. Use Mix.Project.compile_path/1 instead.

# `manifest_path`

```elixir
@spec manifest_path(keyword()) :: Path.t()
```

Returns the path where manifests are stored.

By default they are stored in the app path inside
the build directory. Umbrella applications have
the manifest path set to the root of the build directory.
Directories may be changed in future releases.

The returned path will be expanded.

## Examples

If your project defines the app `my_app`:

    Mix.Project.manifest_path()
    #=> "/path/to/project/_build/shared/lib/my_app/.mix"

# `parent_umbrella_project_file`
*since 1.15.0* 

```elixir
@spec parent_umbrella_project_file() :: binary() | nil
```

Returns the path to the file that defines the parent umbrella project, if one.

The majority of the time, it will point to a `mix.exs` file.
Returns `nil` if not inside a project or not inside an umbrella.

# `project_file`
*since 1.13.0* 

```elixir
@spec project_file() :: binary() | nil
```

Returns the path to the file that defines the current project.

The majority of the time, it will point to a `mix.exs` file.
Returns `nil` if not inside a project.

# `umbrella?`

```elixir
@spec umbrella?(keyword()) :: boolean()
```

Returns `true` if `config` is the configuration for an umbrella project.

When called with no arguments, tells whether the current project is
an umbrella project.

# `with_build_lock`

```elixir
@spec with_build_lock(
  keyword(),
  (-&gt; term())
) :: term()
```

Acquires a lock on the project build path and runs the given function.

When another process (across all OS processes) is holding the lock,
a message is printed and this call blocks until the lock is acquired.
This function can also be called if this process already has the
lock. In such case the function is executed immediately.

This lock is primarily useful for compiler tasks that alter the build
artifacts to avoid conflicts with a concurrent compilation.

---

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