Current section

Files

Jump to
nerves lib mix tasks firmware.ex
Raw

lib/mix/tasks/firmware.ex

defmodule Mix.Tasks.Firmware do
use Mix.Task
import Mix.Nerves.Utils
@shortdoc "Build a firmware bundle"
@moduledoc """
Build a firmware image for the selected target platform.
This task builds the project, combines the generated OTP release with
a Nerves system image, and creates a `.fw` file that may be written
to an SDCard or sent to a device.
## Environment variables
* `NERVES_SYSTEM` - may be set to a local directory to specify the Nerves
system image that is used
* `NERVES_TOOLCHAIN` - may be set to a local directory to specify the
Nerves toolchain (C/C++ crosscompiler) that is used
"""
def run(_args) do
preflight()
debug_info "Nerves Firmware Assembler"
system_path = check_nerves_system_is_set!()
check_nerves_toolchain_is_set!()
rel_config =
File.cwd!
|> Path.join("rel/config.exs")
unless File.exists?(rel_config) do
Mix.raise """
You are missing a release config file. Run nerves.release.init task first
"""
end
Mix.Task.run "compile", []
Mix.Nerves.IO.shell_info "Building OTP Release..."
clean_release()
build_release()
build_firmware(system_path)
end
def result({_ , 0}), do: nil
def result({result, _}), do: Mix.raise """
Nerves encountered an error. #{inspect result}
"""
defp clean_release do
try do
Mix.Task.run "release.clean", ["--implode", "--no-confirm"]
catch
:exit, _ -> :noop
end
end
defp build_release do
Mix.Task.run "release", ["--silent", "--no-tar"]
end
defp build_firmware(system_path) do
config = Mix.Project.config
otp_app = config[:app]
images_path =
(config[:images_path] || Path.join([Mix.Project.build_path, "nerves", "images"]))
|> Path.expand
unless File.exists?(images_path) do
File.mkdir_p(images_path)
end
firmware_config = Application.get_env(:nerves, :firmware)
rel2fw_path = Path.join(system_path, "scripts/rel2fw.sh")
cmd = "bash"
args = [rel2fw_path]
if firmware_config[:rootfs_additions] do
Mix.shell.error("The :rootfs_additions configuration option has been deprecated. Please use :rootfs_overlay instead.")
end
rootfs_overlay = case (firmware_config[:rootfs_overlay] || firmware_config[:rootfs_additions]) do
nil -> []
overlay -> ["-a", Path.join(File.cwd!, overlay)]
end
fwup_conf = case firmware_config[:fwup_conf] do
nil -> []
fwup_conf -> ["-c", Path.join(File.cwd!, fwup_conf)]
end
fw = ["-f", "#{images_path}/#{otp_app}.fw"]
release_path = Path.join(Mix.Project.build_path(), "rel/#{otp_app}")
output = [release_path]
args = args ++ fwup_conf ++ rootfs_overlay ++ fw ++ output
env = standard_fwup_variables(config)
shell(cmd, args, env: env)
|> result
end
defp standard_fwup_variables(config) do
# Assuming the fwup.conf file respects these variable like the official
# systems do, this will set the .fw metadata to what's in the mix.exs.
[{"NERVES_FW_VERSION", config[:version]},
{"NERVES_FW_PRODUCT", config[:name] || to_string(config[:app])},
{"NERVES_FW_DESCRIPTION", config[:description]},
{"NERVES_FW_AUTHOR", config[:author]},
]
end
end