104 lines
2.8 KiB
Elixir
104 lines
2.8 KiB
Elixir
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
|
|
|
|
Artefact.write_checksum_for_target!(precompiled_artefacts)
|
|
|
|
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
|