Current section

Files

Jump to
elixir_make lib mix tasks elixir_make.precompile.ex
Raw

lib/mix/tasks/elixir_make.precompile.ex

defmodule Mix.Tasks.ElixirMake.Precompile do
@shortdoc "Precompiles the given project for all targets"
@moduledoc """
Precompiles the given project for all targets.
This task must only be used by package creators who want to ship the
precompiled NIFs. This task is often used on CI to precompile
for different targets.
This is only supported if `:make_precompiler` is specified
in your project configuration.
"""
alias ElixirMake.Artefact
require Logger
use Mix.Task
@recursive true
@impl true
def run(args) do
if function_exported?(Mix, :ensure_application!, 1) do
Mix.ensure_application!(:inets)
Mix.ensure_application!(:ssl)
Mix.ensure_application!(:crypto)
end
config = Mix.Project.config()
paths = config[:make_precompiler_priv_paths] || ["."]
{_, precompiler} =
config[:make_precompiler] ||
Mix.raise(
":make_precompiler project configuration is required when using elixir_make.precompile"
)
targets = precompiler.all_supported_targets(:compile)
try do
precompiled_artefacts =
Enum.map(targets, fn target ->
case precompiler.precompile(args, target) do
:ok ->
precompiled_artefacts = create_precompiled_archive(config, target, paths)
if function_exported?(precompiler, :post_precompile_target, 1) do
precompiler.post_precompile_target(target)
end
precompiled_artefacts
{:error, msg} ->
Mix.raise(msg)
end
end)
Artefact.write_checksums!(precompiled_artefacts)
if function_exported?(precompiler, :post_precompile, 0) do
precompiler.post_precompile()
else
:ok
end
after
app_priv = Path.join(Mix.Project.app_path(config), "priv")
for include <- paths,
file <- Path.wildcard(Path.join(app_priv, include)) do
File.rm_rf(file)
end
end
end
defp create_precompiled_archive(config, target, paths) do
archive_path = Artefact.archive_path(config, target, :erlang.system_info(:nif_version))
Mix.shell().info("Creating precompiled archive: #{archive_path}")
Mix.shell().info("Paths to archive from priv directory: #{inspect(paths)}")
app_priv = Path.join(Mix.Project.app_path(config), "priv")
File.mkdir_p!(app_priv)
File.mkdir_p!(Path.dirname(archive_path))
artefact =
File.cd!(app_priv, fn ->
filepaths =
for path <- paths,
entry <- Path.wildcard(path),
do: String.to_charlist(entry)
Artefact.compress(archive_path, filepaths)
end)
Mix.shell().info(
"NIF cached at #{archive_path} with checksum #{artefact.checksum} (#{artefact.checksum_algo})"
)
artefact
end
end