Mix
What is Mix?
Mix is a build too that comes with Elixir. It provides tasks for creating new applications, managing dependencies, testing, compilation and more. Mix is a crucial tool for building and managing Elixir applications. Therefore, it's important to have at least a rudimentary understanding of its operation.
Mix tasks are run from the command line. For a list of available tasks, run mix help
. To see more information about a command, run mix help
, followed by the name of the command. For example, running mix help run
will print the following results:
mix run
Starts and runs the current application.
mix run can be used to start the current application dependencies ant the
application itself. For long running systems, this is typically done with the
--no-halt option:
mix run --no-halt
If there is a desire to execute a script within the current application or
configure the application via command line flags, it is possible to do so by
passing a script file or an eval expression to the command:
mix run my_app_script.exs arg1 arg2 arg3
mix run -e "MyApp.start" -- arg1 arg2 arg3
## ...shortened for brevity... ##
Mix new
To create a new Elixir application, run mix new
, followed by the name of the application. For example, mix new blogger
, creates a "blogger" directory that contains a brand new Elixir application. The contents of our new Elixir app are as follows:
/blogger
/config
-config.exs
/lib
-blogger.ex
/test
-blogger_test.exs
-test_helper.exs
.formatter.exs
.gitignore
mix.exs
README.md
Mix creates for us three folders in our root (blogger) directory:
- config - application configuration
- lib - the main folder where application code will go
- test - the folder for application tests and test helpers
We have some files in our root directory to help get us started. The most important file is mix.exs
. We will explore this in more depth throughout the remainder of this chapter. We also have three additional files:
- readme - useful for providing application information such as how to start and configure the application
- formatter - a hidden file used by Elixir versions >= 1.6 to help properly format Elixir code
- gitignore - a hidden file used by git for excluding particular files and folders from source control
From the command line, we can ensure our application is set up correctly by running mix test
. This will run our two application tests that are included by default. The result of this task should be , "1 doctest, 1 test, 0 failures". As you can see, mix starts us off with 1 unit test and 1 doctest. We will explore more on testing in a later chapter. For now, it's only important to realize that Elixir puts an emphasis on both testing and documentation. These are two critical factors in writing high quality code and so the Elixir language has built-in support both.
Environments
Mix supports three distinct environments by default:
- :dev - Development - the default environment for local development
- :test - Test - the environment used by
mix test
for testing code - :prod - Production - the environment used to run projects in production
We can specify an environment to start an application by setting the MIX_ENV variable. For example, to start an application in production:
MIX_ENV=prod iex -S mix
Dependency management
Retrieve a dependency from
- Local file system
- Github
- Hex Package Manager
Project dependencies are listed in the mix.exs
file, within the private function deps
. This function takes a list of dependencies, supplied as tuples. Dependencies must be specified using one of the following formats:
{dep, requirement}
{dep, opts}
{dep, requirement, opts}
Where:
- dep is the name of the dependency, given as an atom
- requirement is a version requirement
- opts is a keyword list of options
By default, dependencies are fetched using the Hex package manager.
In most cases, you'll use a two-element tuples where the first element is the name of the dependency and the second is the version (see the hex example below). You may also specify a dependency hosted on github by specifying git:
or github:
and providing the path.
Examples
HEX { :earmark, "~> 1.0.0" }
LOCAL {:dictionary, path:"../dictionary"}
GITHUB {:foobar, git: "https://github.com/elixir-lang/foobar.git", tag: "0.1"}
In some cases, you may only want to use a dependency in the development or test environment. To do this, pass the environment as an option, {:ex_machina, "~>2.1", only: :test}
.
Dependency versioning
Third party libraries use semantic versioning to identify releases of software. The syntax for semantic versioning is represented by three numbers as follows: MAJOR.MINOR.PATCH. Each number is separated by a period, for example, 1.2.3.
The semantic versioning specification can be found online at this website.
To summarize the specification, given a version number major.minor.patch
, increment each of the following:
- MAJOR version when you make incompatible API changes,
- MINOR version when you add functionality in a backwards-compatible manner, and
- PATCH version when you make backwards-compatible bug fixes.
Custom Mix tasks
In addition to the standard tasks provided by Mix, there is an option to create custom Mix tasks. The convention is to place custom Mix tasks in the lib/mix/tasks
directory, naming the file after the task it performs. We can create a simple greeting task as an example.
defmodule Mix.Tasks.Hello.Greeting do
use Mix.Task
@shortdoc "Sends a greeting to us from Hello Phoenix"
@moduledoc """
This is where we would put any long form documentation or doctests.
"""
def run(_args) do
Mix.Task.run "app.start"
Mix.shell.info "This custom mix task has access to the Repo and Erlang VM"
end
# We can define other functions as needed.
end
We created the file lib/mix/tasks/hello.greeting.ex
. The use
directive allows us to use a given module in the current context. The @shortdoc
is useful because it will show the message whenever a user types mix help
.
A custom Mix task should define a function called run
, in our example we are simply printing out info to the console. After saving the file, we can compile with "elixirc lib/mix/tasks/hello.greeting.ex". This will create a .beam
file in our directory. To execute our mix task we simply run mix
followed by the file name, mix hello.greeting
. The output is as follows, "This custom mix task has access to the Repo and Erlang VM".