Packages
nerves
1.12.0
1.15.0
1.14.3
1.14.2
1.14.1
1.14.0
1.13.2
1.13.1
1.13.0
1.12.0
1.11.3
1.11.2
1.11.1
1.11.0
1.10.5
1.10.4
1.10.3
1.10.2
1.10.1
1.10.0
1.9.3
1.9.2
retired
1.9.1
1.9.0
1.8.0
1.7.17
1.7.16
1.7.15
1.7.14
retired
1.7.13
1.7.12
1.7.11
1.7.10
1.7.9
1.7.8
1.7.7
1.7.6
1.7.5
1.7.4
1.7.3
1.7.2
retired
1.7.1
retired
1.7.0
retired
1.6.7
1.6.6
1.6.5
1.6.4
1.6.3
1.6.2
1.6.1
1.6.0
1.5.5
1.5.4
1.5.3
1.5.2
1.5.1
1.5.0
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.4
1.3.3
1.3.2
1.3.1
1.3.0
1.2.1
1.2.0
1.1.1
1.1.0
1.0.1
1.0.0
1.0.0-rc.2
1.0.0-rc.1
1.0.0-rc.0
0.11.0
0.10.1
0.10.0
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.3
0.8.2
0.8.1
0.8.0
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.1
0.6.0
0.5.2
0.5.1
0.5.0
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.4.0-rc.0
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.0
Craft and deploy bulletproof embedded software
Current section
Files
Jump to
Current section
Files
lib/nerves/package.ex
# SPDX-FileCopyrightText: 2016 Justin Schneck
# SPDX-FileCopyrightText: 2017 Frank Hunleth
# SPDX-FileCopyrightText: 2017 Greg Mefford
# SPDX-FileCopyrightText: 2022 Jon Carstens
#
# SPDX-License-Identifier: Apache-2.0
#
defmodule Nerves.Package do
@moduledoc """
Defines a Nerves package struct and helper functions.
A Nerves package is a Mix application that defines the configuration for a
Nerves system or Nerves toolchain. For more details, see the Nerves
[system documentation](https://hexdocs.pm/nerves/systems.html#package-configuration)
"""
alias Nerves.Artifact
defstruct app: nil,
path: nil,
dep: nil,
env: [],
type: nil,
version: nil,
platform: nil,
build_runner: nil,
compilers: [],
dep_opts: [],
config: []
@type t :: %__MODULE__{
app: atom,
path: binary,
env: %{String.t() => String.t()},
type:
:system
| :package
| :toolchain
| :system_platform
| :toolchain_platform,
dep:
:project
| :path
| :hex
| :git,
platform: atom,
build_runner: {module(), Keyword.t()},
compilers: [atom],
dep_opts: Keyword.t(),
version: Version.t(),
config: Keyword.t()
}
@required [:type, :version, :platform]
@doc """
Loads the package config and parses it into a `%Package{}`
"""
@spec load_config({app :: atom, path :: String.t()}) :: Nerves.Package.t()
def load_config({app, path}) do
config = config(app, path)
version = config[:version]
type = config[:nerves_package][:type]
compilers = config[:compilers] || Mix.compilers()
env = Map.new(config[:nerves_package][:env] || %{})
if !type do
Mix.shell().error(
"The Nerves package #{app} does not define a type.\n\n" <>
"Verify that the key exists.\n"
)
exit({:shutdown, 1})
end
platform = config[:nerves_package][:platform]
build_runner = Artifact.build_runner(config)
config = Enum.reject(config[:nerves_package], fn {k, _v} -> k in @required end)
%__MODULE__{
app: app,
type: type,
env: env,
platform: platform,
build_runner: build_runner,
compilers: compilers,
dep_opts: nerves_options_on_dep(app),
dep: dep_type(app),
path: path,
version: version,
config: config
}
end
# Return the nerves options that the user specified on the dependency
# E.g.,
# {:nerves_system_rpi4, "~> 1.28", runtime: false, targets: :rpi4, nerves: [compile: true]}
# ^^^^^^^^^^^^^^^
defp nerves_options_on_dep(app) do
load_env_deps()
|> Enum.find(%{}, &(&1.app == app))
|> Map.get(:opts, [])
|> Keyword.get(:nerves, [])
end
if Version.match?(System.version(), ">= 1.16.0") do
defp load_env_deps() do
Mix.Dep.Converger.converge(env: Mix.env())
end
else
defp load_env_deps() do
# deprecated in Elixir >= 1.16.0
Mix.Dep.load_on_environment(env: Mix.env())
end
end
@doc """
Starts an interactive shell with the working directory set
to the package path
"""
@spec shell(Nerves.Package.t() | nil) :: :ok
def shell(nil) do
Mix.raise("Package is not loaded in your Nerves Environment.")
end
def shell(%{platform: nil, app: app}) do
Mix.raise("Cannot start shell for #{app}")
end
def shell(pkg) do
pkg.build_runner.shell(pkg)
end
@doc """
Get Mix.Project config for an application
"""
@spec config(Application.app(), Path.t()) :: Keyword.t()
def config(app, path) do
if app == Mix.Project.config()[:app] do
Mix.Project.config()
else
Mix.Project.in_project(app, path, fn _mod ->
Mix.Project.config()
end)
end
end
defp dep_type(pkg) do
deps_paths = Mix.Project.deps_paths()
case Map.get(deps_paths, pkg) do
nil ->
:project
path ->
deps_path =
File.cwd!()
|> Path.join(Mix.Project.config()[:deps_path])
|> Path.expand()
if String.starts_with?(path, deps_path) do
:hex
else
:path
end
end
end
end