defmodule Mix.Nerves.Preflight do @moduledoc false alias Nerves.Utils.WSL @fwup_semver "~> 1.8" @doc """ Run the preflight checks for the Nerves System """ @spec check!() :: any() def check!() do :os.type() |> case do {_, :linux} -> if WSL.running_on_wsl?(), do: :wsl, else: :linux {_, type} -> type end |> check_platform!() Mix.Task.run("nerves.loadpaths") end # OSX defp check_platform!(:darwin) do ensure_fwup_version!() ensure_available!("mksquashfs", package: "squashfs") ensure_available!("gstat", package: "gstat (coreutils)") end # NOTE: We currently require fwup to be installed both in WSL and in Windows # because the fwup.exe in Windows is used when burning firmware to a physical # memory card, and fwup in WSL is used for most other operations. # # WSL 2 adds some new lower-level integrations that may eliminate the need # for this in the future, but we'll need to do some more research. defp check_platform!(:wsl) do ensure_fwup_version!() ensure_fwup_version!("fwup.exe") ensure_available!("mksquashfs", package: "squashfs") end # Non-WSL Linux defp check_platform!(_) do ensure_fwup_version!() ensure_available!("mksquashfs", package: "squashfs") end @doc """ Ensure fwup executable is available and is the expected version """ @spec ensure_fwup_version!(String.t(), String.t()) :: :ok def ensure_fwup_version!(fwup_bin \\ "fwup", vsn_requirement \\ @fwup_semver) do ensure_available!(fwup_bin) case Nerves.Port.cmd(fwup_bin, ["--version"]) do {vsn, 0} -> vsn = String.trim(vsn) {:ok, req} = Version.parse_requirement(vsn_requirement) unless Version.match?(vsn, req) do Mix.raise(""" #{fwup_bin} #{vsn_requirement} is required for Nerves. You are running #{vsn}. Please see https://hexdocs.pm/nerves/installation.html#fwup for installation instructions """) end error -> Mix.raise(""" Nerves encountered an error while checking host requirements for fwup #{inspect(error)} Please open a bug report for this issue on github.com/nerves-project/nerves """) end :ok end @doc """ Ensure that the given command is available in the system path """ @spec ensure_available!(String.t(), Keyword.t()) :: :ok def ensure_available!(executable, opts \\ []) do if System.find_executable(executable) do :ok else package = opts[:package] || executable Mix.raise(missing_package_message(package)) end end defp missing_package_message(package) do """ #{package} is required by the Nerves tooling. Please see https://hexdocs.pm/nerves/installation.html for installation instructions. """ end end