View Source Updating Projects
Please review this guide before updating your projects. Help is available via the Elixir forum. Please file bugs on GitHub.
Contents:
- Updating from v0.8 to v0.9
- Updating from v0.9 to v1.0.0-rc.0
- Updating from v1.0.0-rc.0 to v1.0.0-rc.2
- Updating from v1.0 to v1.3
- Updating from v1.3 to v1.4
- Updating from v1.4 to v1.5
- Updating from v1.5 to v1.6
- Updating from v1.6 to v1.7
Updating from v0.8 to v0.9
Nerves v0.9.0 contains changes that require updates to existing projects. All
users are highly encouraged to update, but if you cannot, be sure to force the
Nerves version in your mix.exs
dependencies.
Update Nerves Bootstrap to v0.8.1
Nerves Bootstrap is an Elixir archive that provides a new project generator and
some logic required for the Nerves integration into mix
. Nerves v0.9 requires
updates to this archive.
Install the latest Nerves Bootstrap archive by running:
mix local.nerves
or
mix archive.install hex nerves_bootstrap
Update mix.exs aliases (old)
IMPORTANT: If you're upgrading to Nerves v1.0, this step has been superseded.
Nerves requires that you add aliases to your project's mix.exs
to pull in the
firmware creation and compilation logic. Previously, you needed to know
which aliases to override. Nerves v0.9 added a new alias. Rather than add this
alias, we recommend using the new alias helper in your mix.exs
. To do this,
edit the target aliases function to look like this:
defp aliases(_target) do
[
# Add custom mix aliases here
]
|> Nerves.Bootstrap.add_aliases()
end
This only works with nerves_bootstrap
v0.7.0 and later, so if you get an
error, be sure to update your Nerves Bootstrap as described in the previous
section.
For those interested in more details, the reason behind this change was to move
precompiled artifact downloads from the mix compile
step to the mix deps.get
step. That entailed adding additional logic to the deps.get
step and hence an
additional alias.
Replace Bootloader with Shoehorn
During this release, we renamed one of our dependencies from bootloader
to
shoehorn
to prevent overloading the term bootloader in the embedded space.
This requires a few updates:
First, update the dependency by changing:
{:bootloader, "~> 0.1"}
to
{:shoehorn, "~> 0.2"}
Next, update the distillery release config in rel/config.exs
. Look for the
line near the end that looks like:
plugin Bootloader.Plugin
or
plugin Bootloader
and change it to
plugin Shoehorn
Finally, change references to bootloader
in your config/config.exs
to
shoehorn
. For example, change:
config :bootloader,
init: [:nerves_runtime],
app: :my_app
to
config :shoehorn,
init: [:nerves_runtime],
app: :my_app
Artifact checksums
Some Nerves dependencies reference a large precompiled version of their build products to significantly reduce compilation time. These are called artifacts and due to their size, they cannot be hosted on hex.pm. Nerves downloads these automatically as part of the dependency resolution process. It is critical that they match the corresponding source code and the previous method of checking version numbers was insufficient. Nerves v0.9.0 now uses a checksum of the projects source files. This works for all projects no matter what version control system they use or how they are stored.
If you have created a custom Nerves system or toolchain, you will need to update
your project's mix.exs
to ensure that the checksum covers the right files.
This is done using the :checksum
key on the nerves_package
. Since the files
that you checksum are likely identical to those published on hex.pm, we
recommend creating a package_files/0
function that's used by both.
Here's an example from nerves-project/nerves_system_rpi0
:
def nerves_package do
[
# ... Other Options
checksum: package_files()
]
end
defp package do
[
files: package_files(),
licenses: ["Apache 2.0"],
links: %{"Github" => "https://github.com/nerves-project/#{@app}"}
]
end
defp package_files do
[
"LICENSE",
"mix.exs",
"nerves_defconfig",
"README.md",
"VERSION",
"rootfs_overlay",
"fwup.conf",
"fwup-revert.conf",
"post-createfs.sh",
"post-build.sh",
"cmdline.txt",
"linux-4.4.defconfig",
"config.txt"
]
end
Easier artifact creation
Prior to Nerves v0.9.0, creating artifacts for Nerves systems and toolchains
required manual steps. Nerves v0.9.0 adds the nerves.artifact
mix task to make
this easier. Please update your CI scripts or build instructions to use this new
method.
Nerves makes it easier to predigest artifacts for systems and toolchains
with the added mix task mix nerves.artifact <app_name>
. Omitting <app_name>
will default to the app name of the parent mix project. This is useful if
you are calling mix nerves.artifact
from within a custom system or toolchain
project.
For example, lets say we have a custom rpi0
system and we would like to
create an artifact. mix nerves.artifact custom_system_rpi0
This will produce a file in the current working directory with a name of the format
<app_name>-<host_tuple | portable>-<version>-<checksum><extension>
For example,
custom_system_rpi0-portable-0.11.0-17C58821DE265AC241F28A0A722DB25C447A7B5FFF5648E4D0B99EF72EB3341F.tar.gz
Artifact sites
Once you've created the artifact (or had CI create it for you),
you can then upload this to Github releases and instruct the artifact resolver
to fetch this artifact following deps.get
. Update the Nerves package config
by editing the :nerves_package
options of Mix.project/0
for your custom
system or toolchain to set the sites for which the artifact is available on.
This can be passed as
{:github_releases, "<organization>/<repository>"}
or specified as url / path prefixes
{:prefix, "/path/to/artifact_dir"}
{:prefix, http://artifact_server.com/artifacts}
def nerves_package do
[
# ... Other Options
artifact_sites: [
{:github_releases, "nerves-project/custom_system_rpi0"}
]
]
end
The artifact resolver will attempt to fetch from each site listed until it successfully retrieves an artifact or it reaches the end of the list.
Updating from v0.9 to v1.0.0-rc.0
Update to Nerves Bootstrap v1.0.0-rc.0
Nerves Bootstrap is an Elixir archive that provides a new project generator and
some logic required for the Nerves integration into mix
. Nerves v1.0-rc
requires updates to this archive.
Install the latest Nerves Bootstrap archive by running:
mix local.nerves
or
mix archive.install hex nerves_bootstrap
Update project dependencies
You will need to update the version string for nerves
and nerves_bootstrap
in your projects to enable the usage of 1.0-rc
. Open your mix.exs
file and
start by updating the nerves_bootstrap
archive:
# mix.exs
def project do
[
# ...
archives: [{:nerves_bootstrap, "~> 1.0-rc"}],
]
end
Then update the nerves dep:
# Run "mix help deps" to learn about dependencies.
defp deps do
[{:nerves, "~> 1.0-rc", runtime: false}] ++ deps(@target)
end
You may have to set override: true
if you are using other Nerves packages that
have not been updated to depend on Nerves 1.0-rc yet
If you wish to revert, you lock to a specific version using ~> 0.8.0
or = 0.8.0
Update mix.exs aliases
nerves_bootstrap
1.0-rc manages its own aliases on Application.start/1
and
is invoked by setting MIX_TARGET
to value other then host
. Update your
mix.exs
file to add the bootstrap/1
function and change the aliases to
[loadconfig: [&bootstrap/1]]
:
# mix.exs
def project do
[
# ...
aliases: [loadconfig: [&bootstrap/1]],
]
end
# Starting nerves_bootstrap pulls in the Nerves hooks to mix, but only
# if the MIX_TARGET environment variable is set.
defp bootstrap(args) do
Application.start(:nerves_bootstrap)
Mix.Task.run("loadconfig", args)
end
Updating from v1.0.0-rc.0 to v1.0.0-rc.2
Updating Provider to BuildRunner
This only applies to custom systems and host tools
Nerves v1.0.0-rc.2 renames the module Nerves.Artifact.Provider
to
Nerves.Artifact.BuildRunner
.
The nerves_package
config allowed the package to override
provider
and provider_opts
. These keys have been renamed to
build_runner
and build_runner_opts
For example:
def nerves_package do
[
# ..
build_runner: Nerves.Artifact.BuildRunners.Docker,
# ..
]
end
Updating from v1.0 to v1.3
Modify the release config
Nerves now runs as a distillery plugin instead of inside the rel/config.exs
.
You will need to change your rel/config.exs
. Find the section near the bottom
of the file that defines your application.
Change this:
release :my_app do
set version: current_version(:my_app)
plugin Shoehorn
if System.get_env("NERVES_SYSTEM") do
set dev_mode: false
set include_src: false
set include_erts: System.get_env("ERL_LIB_DIR")
set include_system_libs: System.get_env("ERL_SYSTEM_LIB_DIR")
set vm_args: "rel/vm.args"
end
end
To this:
release :my_app do
set version: current_version(:my_app)
plugin Shoehorn
plugin Nerves
end
Update shoehorn dependency
You will need to update your version of shoehorn to {:shoehorn, "~> 0.4"}
.
Updating from v1.3 to v1.4
Version v1.4.0 adds support for Elixir 1.8's new built-in support for mix
targets. In Nerves, the MIX_TARGET
was used to select the appropriate set of
dependencies for a device. This lets you switch between building for different
boards and your host. Elixir 1.8 pulls this support into mix
and lets you
annotate dependencies for which targets they should be used.
Update your mix.exs file
The @target
is no longer used. Delete it and then add @all_targets
like this:
@target System.get_env("MIX_TARGET") || "host"
@all_targets [:rpi0, :rpi3, :rpi]
The @all_targets
alias will be convenient when updating the dependencies in
your mix.exs
. Set it to the target names that you use (in atom form). Like the
previous use of MIX_TARGET
, it didn't matter what you called the targets. It
only mattered that you were consistent.
The :host
target refers to compilation for your computer. It's the only
special target and is used for running non-hardware-specific unit tests.
Next, remove the following lines from the project/0
callback (yay Elixir 1.8):
target: @target
deps_path: "deps/#{@target}"
build_path: "_build/#{@target}"
lockfile: "mix.lock.#{@target}"
Change build_embedded
from
build_embedded: @target != "host"
to
build_embedded: Mix.target() != :host,
The next step is to consolidate your dependencies to one deps/0
function.
Nerves previously grouped dependencies and used pattern matches to pick the
right ones for your device. Elixir 1.8 makes this unnecessary.
Now Elixir can fetch and lock your dependencies for all targets. Previously, if you'd switch targets, your dependencies might change versions. No more!
Elixir 1.8 adds the :targets
option on dependencies. Here's an example:
Before:
# Run "mix help deps" to learn about dependencies.
# Dependencies for all targets
defp deps do
[
{:nerves, "~> 1.3", runtime: false},
{:shoehorn, "~> 0.4"},
{:ring_logger, "~> 0.6"},
{:toolshed, "~> 0.2"}
] ++ deps(@target)
end
# Specify target specific dependencies
defp deps("host"), do: []
# Dependencies for all targets except :host
defp deps(target) do
[
{:nerves_runtime, "~> 0.6"},
{:nerves_init_gadget, "~> 0.4"}
] ++ system(target)
end
# Dependencies for specific targets
defp system("rpi"), do: [{:nerves_system_rpi, "~> 1.5", runtime: false}]
defp system("rpi0"), do: [{:nerves_system_rpi0, "~> 1.5", runtime: false}]
defp system("rpi2"), do: [{:nerves_system_rpi2, "~> 1.5", runtime: false}]
defp system("rpi3"), do: [{:nerves_system_rpi3, "~> 1.5", runtime: false}]
defp system("bbb"), do: [{:nerves_system_bbb, "~> 2.0", runtime: false}]
defp system("x86_64"), do: [{:nerves_system_x86_64, "~> 1.5", runtime: false}]
defp system(target), do: Mix.raise("Unknown MIX_TARGET: #{target}")
After:
# Run "mix help deps" to learn about dependencies.
defp deps do
[
# Dependencies for all targets
{:nerves, "~> 1.4", runtime: false},
{:shoehorn, "~> 0.4"},
{:ring_logger, "~> 0.6"},
{:toolshed, "~> 0.2"},
# Dependencies for all targets except :host
{:nerves_runtime, "~> 0.6", targets: @all_targets},
# Dependencies for specific targets
{:nerves_system_rpi, "~> 1.5", runtime: false, targets: :rpi},
{:nerves_system_rpi0, "~> 1.5", runtime: false, targets: :rpi0},
{:nerves_system_rpi2, "~> 1.5", runtime: false, targets: :rpi2},
{:nerves_system_rpi3, "~> 1.5", runtime: false, targets: :rpi3},
{:nerves_system_rpi3a, "~> 1.5", runtime: false, targets: :rpi3a},
{:nerves_system_bbb, "~> 2.0", runtime: false, targets: :bbb},
{:nerves_system_x86_64, "~> 1.5", runtime: false, targets: :x86_64}
]
end
Update config.exs
Accessing the MIX_TARGET
is done differently now. References in your
config.exs
to Mix.Project.config[:target]
need to be Mix.target()
now. For
example, change this:
import_config "#{Mix.Project.config[:target]}.exs
to:
import_config "#{Mix.target()}.exs"
Update application.ex
Search your Elixir code for references to Mix.Project.config()[:target]
. These
need to change as well. It's not uncommon to have these in your application.ex
to decide what to start in your main supervision tree. For example, change this:
@target Mix.Project.config()[:target]
to:
@target Mix.target()
Updating from v1.4 to v1.5
Nerves v1.5 adds support for Elixir 1.9+ releases. Previous versions of Nerves only supported Distillery for OTP release creation. Nerves v1.5 still supports Distillery, but it is no longer included by default. Nerves v1.5 also still supports previous Elixir versions, so there is no need to update to Elixir 1.9.
The most important part of the Nerves v1.5 upgrade process is to make sure that Nerves knows whether you want to use Elixir 1.9 releases or Distillery. Please find the subsections below that correspond to your environment.
Update nerves_bootstrap
Nerves now requires nerves_bootstrap
1.5.1 and later. Assuming that you
already have it installed, run:
mix local.nerves
nerves_bootstrap
v1.6.0 and later generate Elixir 1.9-based projects. This
functionality does not affect existing projects if you are not updating your
Elixir version. However, if you cannot update Elixir and still want to create
new projects, force the nerves_bootstrap
installation to ~> 1.5.0
:
mix archive.install hex nerves_bootstrap "~> 1.5.0"
Update Elixir < 1.9.0 projects
If you're not updating to Elixir 1.9, then Distillery is your only option for OTP release creation and must be explicitly specified. The following steps will ensure that your project has the appropriate updates:
In your mix.exs
, add distillery as a dependency of your project:
{:distillery, "~> 2.1"}
Distillery 2.1 moved code out of the Mix.Releases
namespace. This requires a
change to your project's rel/config.exs
. Open rel/config.exs
and look for
the following line:
use Mix.Releases.Config
Change it to:
use Distillery.Releases.Config
Finally, check that the :shoehorn
dependency is ~> 0.6
:
{:shoehorn, "~> 0.6"}
Run mix deps.get
and your project should continue to work.
At this point, consider updating your Nerves system to the latest to pull in Linux, Erlang, and other C library and application updates.
Update Elixir ~> 1.9
First verify that you have nerves_bootstrap
1.6.0 or later installed:
$ mix archive
* hex-0.20.1
* nerves_bootstrap-1.6.0
The following instructions are for updating your project files to use Elixir 1.9
releases. If you must use Distillery, see the instructions above for Elixir < 1.9.0
projects.
mix.exs updates
In your project's mix.exs
, make the following edits:
Move the application name to a module attribute:
@app :my_app def project do [ app: @app # ... ] end
Add release config to the project config:
def project do [ # ... releases: [{@app, release()}] ] end def release do [ overwrite: true, cookie: "#{@app}_cookie", include_erts: &Nerves.Release.erts/0, steps: [&Nerves.Release.init/1, :assemble], strip_beams: Mix.env() == :prod ] end
Update the nerves and shoehorn dependencies
def deps [ {:nerves, "~> 1.5.0", runtime: false}, {:shoehorn, "~> 0.6"}, # ... ] end
Update the required archives:
def project do [ # ... archives: [nerves_bootstrap: "~> 1.6"], ] end
Add preferred CLI target to the project config:
def project do [ # ... preferred_cli_target: [run: :host, test: :host] ] end
vm.args updates
Next, rename rel/vm.args
to rel/vm.args.eex
Then update the line that sets the cookie to
-setcookie <%= @release.options[:cookie] %>
Erase old Distillery files
Since Distillery is no longer being used, erase any Distillery configuration files that are still around. For most Nerves users, run the following:
rm rel/config.exs
rm rel/plugins/.gitignore
Nerves system update
Elixir 1.9+ releases are only compatible with systems that contain erlinit ~> 1.5
.
If you are using an official Nerves system, then make sure that you are using one of these versions:
nerves_system_rpi: ~> 1.8
nerves_system_rpi2: ~> 1.8
nerves_system_rpi3: ~> 1.8
nerves_system_rpi3a: ~> 1.8
nerves_system_rpi0: ~> 1.8
nerves_system_x86_64: ~> 1.8
nerves_system_bbb: ~> 2.3
If you are using a custom system, you will need to update nerves_system_br
to
a version that is >= 1.8.1
.
config.exs updates
Nerves has been improving support for "host" builds of firmware projects. This
makes it possible to unit test platform-independent code on your build machine.
To take advantage of this, it's important to separate out the target-dependent
sections of the config.exs
. Here's one way of doing this:
Create a new file
config/target.exs
Move configs for applications that are only available on the target to the
target.exs
file.Update
config.exs
to importtarget.exs
if the target is nothost
.if Mix.target() != :host do import_config "target.exs" end
Updating from v1.5 to v1.6
Nerves 1.6 adds support for Elixir 1.10. In truth, only the internals of the Nerves tooling were changed. As a result of this change, we made the decision to drop support for Elixir 1.6 and Erlang 20. If you are still using these older versions, you'll need to update to at least Elixir 1.7 and Erlang 21. Then update to Nerves 1.6.
To update your projects to use Nerves 1.6, bump the :nerves
dependency in your
project's mix.exs
:
defp deps do
[
...
{:nerves, "~> 1.6.0", runtime: false},
...
]
end
Run mix deps.get
and build as normal. You may also need to update your Nerves
system to a newer official build. Many systems have dependency requirements on
Nerves 1.5 that can be updated to Nerves 1.6 without issue. Please review the
Nerves system release notes when you upgrade.
Updating from v1.6 to v1.7
The only backwards incompatible change in Nerves 1.7 is to remove Distillery support. See Updating from v1.4 to v1.5 for how to move to mix releases.