View Source Systems

using-a-nerves-system

Using a Nerves System

When you generate a new Nerves project using the mix nerves.new task, you will end up with something like the following in your mix.exs configuration:

  # ...
  @target System.get_env("MIX_TARGET") || "host"
  # ...
  defp deps do
    [
      {:nerves, "~> 1.3", runtime: false},
      {:shoehorn, "~> 0.4"},
      {:ring_logger, "~> 0.4"}
    ] ++ deps(@target)
  end

  defp deps("host"), do: []

  defp deps(target) do
    [
      {:nerves_runtime, "~> 0.6"}
    ] ++ system(target)
  end

  def system("rpi"), do: {:nerves_system_rpi, "~> 1.0", runtime: false}
  def system("rpi0"), do: {:nerves_system_rpi0, "~> 1.0", runtime: false}
  # ...
  def system(target), do: Mix.raise "Unknown MIX_TARGET: #{target}"

This allows Nerves to load one or more target-specific dependencies when a MIX_TARGET system environment variable is specified. The official nerves_system-* dependencies contain the standard Buildroot configuration for the Nerves platform on a given hardware target and have a dependency on the appropriate toolchain for that target. The system and toolchain also reference a pre-compiled version of the relevant artifact so that Mix can simply download them instead of having to compile them (which takes quite a while).

compatibility

Compatibility

The Nerves System (nerves_system_*) dependency determines the OTP version running on the target. It is possible that a recent update to the Nerves System pulled in a new version of Erlang/OTP. If you are using an official Nerves System, you can verify this by reviewing the chart below or CHANGELOG.md file that comes with the release.

bbbrpirpi0rpi2rpi3rpi3arpi4osd32mp1x86_64grisp2
OTP 25.02.14.01.19.01.19.01.19.01.19.01.19.01.19.00.10.01.19.00.3.0
OTP 24.3.22.13.41.18.41.18.41.18.41.18.41.18.41.18.40.9.41.18.40.2.3
OTP 24.2.22.13.31.18.31.18.31.18.31.18.31.18.31.18.30.9.31.18.30.2.2
OTP 24.22.13.21.18.21.18.21.18.21.18.21.18.21.18.20.9.21.18.20.2.0
OTP 24.1.72.12.31.17.31.17.31.17.31.17.41.17.31.17.30.8.31.17.3
OTP 24.1.42.12.21.17.21.17.21.17.21.17.31.17.21.17.20.8.21.17.2
OTP 24.1.22.12.11.17.11.17.11.17.11.17.21.17.11.17.10.8.11.17.1
OTP 24.12.12.01.17.01.17.01.17.01.17.11.17.01.17.00.8.01.17.0
OTP 24.0.52.11.21.16.21.16.21.16.21.16.21.16.21.16.30.7.21.16.2
OTP 24.0.22.11.11.16.11.16.11.16.11.16.11.16.11.16.10.7.11.16.1
OTP 23.3.12.10.11.15.11.15.11.15.11.15.11.15.11.15.10.6.11.15.1
OTP 23.2.72.10.01.15.01.15.01.15.01.15.01.15.01.15.00.6.01.15.0
OTP 23.2.42.9.01.14.11.14.11.14.01.14.01.14.01.14.00.5.01.14.0

Run mix deps to see the Nerves System version and go to that system's repository on https://github.com/nerves-project.

If you need to run a particular version of Erlang/OTP on your target, you can either lock the nerves_system_* dependency in your mix.exs to an older version. Note that this route prevents you from receiving security updates from the official systems. The other option is to build a custom Nerves system. See the Nerves documentation for building a custom system and then run make menuconfig and look for the Erlang options.

anatomy-of-a-nerves-system

Anatomy of a Nerves System

Nerves system dependencies are a collection of configurations to be fed into 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_rpi3
├── LICENSE
├── README.md
├── VERSION
├── cmdline.txt
├── config.txt
├── fwup.conf
├── linux-4.4.defconfig
├── mix.exs
├── nerves_defconfig
├── post-createfs.sh
└── rootfs-overlay
    └── etc
        └── erlinit.config
        └── fw_env.config

The mix.exs defines the toolchain and build platform, for example:

def project do
  [ # ...
   nerves_package: nerves_package(),
   compilers: Mix.compilers ++ [:nerves_package],
   aliases: [loadconfig: [&bootstrap/1]]]
end
# ...
def nerves_package do
  [
    type: :system,
    artifact_sites: [
      {:github_releases, "nerves-project/#{@app}",
    ],
    platform: Nerves.System.BR,
    platform_config: [
      defconfig: "nerves_defconfig"
    ],
    checksum: [
      "nerves_defconfig",
      "rootfs_overlay",
      "linux-4.4.defconfig",
      "fwup.conf",
      "cmdline.txt",
      "config.txt",
      "post-createfs.sh",
      "VERSION"
    ]
  ]
end
# ...
defp deps do
  [
    {:nerves, "~> 1.0", runtime: false},
    {:nerves_system_br, "~> 1.0", runtime: false},
    {:nerves_toolchain_arm_unknown_linux_gnueabihf, "~> 1.0", runtime: false}
  ]
end
# ...
defp package do
 [ # ...
  files: ["LICENSE", "mix.exs", "<other files>"],
  licenses: ["Apache 2.0"],
  links: %{"Github" => "https://github.com/nerves-project/nerves_system_rpi3"}]
end

Nerves systems have a few requirements in the mix file:

  1. The compilers must include :nerves_package compiler after Mix.compilers.
  2. There must be a dependency for the toolchain and the build platform.
  3. The package must specify all the required files so they are present when downloading from Hex.
  4. The nerves_package key should contain nerves package configuration metadata as described in the next section.

nerves-package-configuration

Nerves Package Configuration

The mix.exs project configuration contains a special configuration key nerves_package. This key 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 mix.exs file for nerves_system_rpi3:

# ...
def project do
  [ # ...
   nerves_package: nerves_package(),
    # ...
  ]
end
# ....
defp nerves_package do
  [
    type: :system,
    artifact_sites: [
      {:github_releases, "nerves-project/#{@app}"}
    ],
    platform: Nerves.System.BR,
    platform_config: [
      defconfig: "nerves_defconfig"
    ],
    checksum: package_files()
  ]
end

The following keys are supported:

  1. type: The type of Nerves Package.

    Options are: system, system_compiler, system_platform, system_package, toolchain, toolchain_compiler, toolchain_platform.

  2. artifact_sites (optional): Artifacts for Nerves systems and toolchains are too large for most package managers and must be stored externally. Artifact sites specify how to download artifacts and are attempted in order until one is successfully downloaded.

    Supported artifact sites:

     {:github_releases, "organization/project"}
     {:github_api, "organization/project", username: System.get_env("GITHUB_USER"), token: System.get_env("GITHUB_TOKEN"), tag: @version}
     {:prefix, "http://myserver.com/artifacts"}
     {:prefix, "file:///my_artifacts/"}
     {:prefix, "/users/my_user/artifacts/"}
     {:prefix, "http://myserver.com/artifacts", headers: [{"Authorization", "Basic 12345"}]}
     {:prefix, "http://myserver.com/artifacts", query_params: %{"id" => "1234"}}

    For official Nerves systems and toolchains, we upload the artifacts to GitHub Releases.

    For an artifact site that uses GitHub Releases in a private repo, create a personal access token and use :github_api with username, token, and tag options:

     {:github_api, "owner/repo", username: "skroob", token: "1234567", tag: "v0.1.0"}

    Artifact sites can pass options as a third parameter for adding headers or query string parameters.

     {:prefix, "https://my-organization.com",
       query_params: %{"id" => "1234567", "token" => "abcd"},
       headers: [{"Content-Type", "application/octet-stream"}]
     }

    You can also use this to add an authorization header for files behind basic auth.

     {:prefix, "http://my-organization.com/", headers: [{"Authorization", "Basic " <> System.get_env("BASIC_AUTH")}}]}
  3. platform: The build platform to use for the system or toolchain.

  4. platform_config: Configuration options for the build platform.

    In this example, the defconfig option for the Nerves.System.BR platform points to the Buildroot defconfig fragment file used to build the system.

  5. build_runner: Optional - The build_runner that should be used to build the artifact.

    If this key is not defined, Nerves will choose a default build_runner that should be used to build the artifact based on information about the host computer that you are building on. For example, Mac OS will use Nerves.Artifact.BuildRunners.Docker where as Linux will use Nerves.Artifact.BuildRunners.Local. Specifying a build_runner module in the package config could be used to force the build_runner.

  6. build_runner_opts: Optional - A keyword list of options to pass to the build_runner module.

    make_args: - Extra arguments to be passed to make.

    For example:

    You can configure the number of parallel jobs that Buildroot can use for execution. This is useful for situations where you may have a machine with a lot of CPUs but not enough ram.

     defp nerves_package do
       [
         # ...
         build_runner_opts: [make_args: ["PARALLEL_JOBS=8"]],
       ]
     end
  7. checksum: The list of files for which checksums are calculated and stored in the artifact cache.

    This checksum is used to match the cached Nerves artifact on disk with its source files, so that it will be re-compiled instead of using the cache if the source files no longer match.

customizing-your-own-nerves-system

Customizing Your Own Nerves System

This document has been moved

Is something wrong?Edit this page on GitHub