Systems
Using a Nerves System
Single Target
To use a Nerves system in project with a single target, you can directly include it as part of your application dependencies.
# mix.exs
def deps do
[{:nerves_system_bbb, ">=0.0.0"}]
end
Multi Target
Multi target configurations can be handled a number of ways. You can allow all nerves_system_*
projects by interpolating target
def deps(target) do
[{:"nerves_system_#{target}", ">=0.0.0"}]
end
Or you could switch between different configurations of the same target.
def deps(:dev = env) do
[{:my_custom_bbb_dev, ">=0.0.0"}]
end
def deps(:prod = env) do
[{:my_custom_bbb_prod, ">=0.0.0"}]
end
Since its all done in Elixir, you can choose which configuration works best for you. Just be sure that there is only ever one system
present when compiling your Nerves application.
Designing a Nerves System
Nerves System dependencies are a collection of configurations to be fed into the the system build platform. Currently, Nerves Systems are all built using the Buildroot platform. The project structure of a Nerves System is as follows:
# nerves_system_*
mix.exs
nerves_defconfig
nerves.exs
rootfs-additions
VERSION
The mix file will contain the dependencies the System has. Typically, all that is included here is the Toolchain and the build platform. Here is an example of the Raspberry Pi 3 nerves_system
definition:
defmodule NervesSystemRpi3.Mixfile do
use Mix.Project
@version Path.join(__DIR__, "VERSION")
|> File.read!
|> String.strip
def project do
[app: :nerves_system_rpi3,
version: @version,
elixir: "~> 1.2",
compilers: Mix.compilers ++ [:nerves_system],
description: description,
package: package,
deps: deps]
end
def application do
[]
end
defp deps do
[{:nerves_system, "~> 0.1.2"},
{:nerves_system_br, "~> 0.5.0"},
{:nerves_toolchain_arm_unknown_linux_gnueabihf, "~> 0.6.0"}]
end
defp package do
[maintainers: ["Frank Hunleth", "Justin Schneck"],
files: ["LICENSE", "mix.exs", "nerves_defconfig", "nerves.exs", "README.md", "VERSION", "rootfs-additions"],
licenses: ["Apache 2.0"],
links: %{"Github" => "https://github.com/nerves-project/nerves_system_rpi3"}]
end
end
Nerves Systems have a few requirements in the mix file:
- The compilers must include the
:nerves_system
compiler after theMix.compilers
have executed. - There must be a dependency for the toolchain and the build platform.
- You need to list all files in the
package
files:
list so they are present when downloading from Hex.
Package Configuration
In addition to the mix file, Nerves packages read from a special nerves.exs
configuration file in the root of the package names. This file contains configuration information that Nerves loads before any application or dependency code is compiled. It is used to store metadata about a package. Here is an example from the nerves.exs
file for rpi3
:
use Mix.Config
version =
Path.join(__DIR__, "VERSION")
|> File.read!
|> String.strip
config :nerves_system_rpi3, :nerves_env,
type: :system,
mirrors: [
"https://github.com/nerves-project/nerves_system_rpi3/releases/download/v#{version}/nerves_system_rpi3-v#{version}.tar.gz"],
build_platform: Nerves.System.Platforms.BR,
build_config: [
defconfig: "nerves_defconfig",
package_files: [
"rootfs-additions"
]
]
There are a few important and required keys present in this file:
type The type of Nerves Package. Options are: system
, system_compiler
, system_platform
, system_package
, toolchain
, toolchain_compiler
, toolchain_platform
.
mirrors The URL(s) of cached assets. For nerves systems, we upload the finalized assets to Github releases so others can download them.
build_platform The build platform to use for the system or toolchain.
build_config The collection of configuration files. This collection contains the following keys:
defconfig For
Nerves.System.Platforms.BR
, this is the BuildRoot defconfig fragment used to build the system.kconfig BuildRoot requires a
Config.in
kconfig file to be present in the config directory. If this is omitted, a default empty file is used.- package_files Additional files required to be present for the defconfig. Directories listed here will be expanded and all subfiles and directories will be copied over, too.
Building Nerves Systems
Nerves system dependencies are light-weight, configuration-based dependencies that, at compile time, request to either download from cache, or locally build the dependency. You can control which route nerves_system
will take by setting some environment variables on your machine:
NERVES_SYSTEM_CACHE
Options are none
, http
, local
NERVES_SYSTEM_COMPILER
Options are none
, local
Currently, Nerves systems can only be compiled using the local
compiler on a specially-configured Linux machine. For more information on what is required to set up your host Linux machine, you can read the nerves_system_br
Install Page
Nerves cache and compiler adhere to the Nerves.System.Provider
behaviour. Therefore, the system is laid out to allow additional compiler and cache providers, to facilitate other options in the future like Vagrant or Docker. This will be helpful when you want to start a BuildRoot build on your Mac or Windows host machine.
Using Local Cache Provider
Nerves systems can take up a lot of space on your machine. This is because the dependency needs to be fetched for each project | target | env. To save space, you can enable the local cache.
$ export NERVES_SYSTEM_CACHE=local
With the local cache enabled, Nerves will attempt to find a cached version of the system in the cache dir. The default cache dir is located at ~/.nerves/cache/system
You can override this location by setting NERVES_SYSTEM_CACHE_DIR
env variable.
If the system your project is attempting to use is not present in the cache, mix will prompt you asking if you would like to download it.
$ mix compile
...
==> nerves_system_rpi3
[nerves_system][compile]
[nerves_system][local] Checking Cache for nerves_system_rpi3-0.5.1
nerves_system_rpi3-0.5.1 was not found in your cache.
cache dir: /Users/jschneck/.nerves/cache/system
Would you like to download the system to your cache? [Yn] Y
This will invoke the http provider and attempt to resolve the dependency.
Creating or Modifying a Nerves System
The easiest way to create a new Nerves system is to check out nerves_system_br
and create a configuration that contains the packages and configuration you need. Once you get this working and booting on your target, you can copy the configurations and files back into a new mix project following the structure described above.