Current section
Files
Jump to
Current section
Files
lib/mix/tasks/compile.rambo.ex
defmodule Mix.Tasks.Compile.Rambo do
@moduledoc false
use Mix.Task.Compiler
# rust targets
@mac "x86_64-apple-darwin"
@linux "x86_64-unknown-linux-musl"
@windows "x86_64-pc-windows-gnu"
@filenames %{
@mac => "rambo-mac",
@linux => "rambo-linux",
@windows => "rambo.exe",
:custom => "rambo"
}
@environment List.to_string(:erlang.system_info(:system_architecture))
filename =
cond do
String.starts_with?(@environment, "x86_64-apple-darwin") ->
@filenames[@mac]
String.starts_with?(@environment, "x86_64") and String.contains?(@environment, "linux") ->
@filenames[@linux]
@environment == "win32" ->
@filenames[@windows]
true ->
@filenames.custom
end
@filename filename
def find_rambo do
Path.join(:code.priv_dir(:rambo), @filename)
end
def run(["bundled"]) do
with :ok <- compile(@mac),
:ok <- compile_in_docker(@linux),
:ok <- compile_in_docker(@windows) do
:ok
else
error -> error
end
end
def run(_args) do
executable = find_rambo()
unless File.exists?(executable), do: compile!()
if Application.get_env(:rambo, :purge, false) do
remove_unused_binaries(executable)
end
:ok
end
@compile_priv_dir "#{:code.priv_dir(:rambo)}"
defp remove_unused_binaries(executable) do
filename = Path.basename(executable)
@filenames
|> Enum.map(fn {_target, filename} -> filename end)
|> Enum.reject(&(&1 == filename))
|> Enum.map(&Path.join(@compile_priv_dir, &1))
|> Enum.each(&File.rm/1)
end
defp compile! do
if System.find_executable("cargo") do
compile(:custom)
else
raise """
Rambo does not ship with binaries for your environment.
#{@environment} detected
Install the Rust compiler so a binary can be prepared for you.
"""
end
end
defp compile(target) do
args =
case target do
:custom -> ["build", "--release"]
target -> ["build", "--release", "--target", target]
end
case System.cmd("cargo", args, cd: @compile_priv_dir) do
{_output, 0} ->
move_executable(target)
:ok
{output, _exit_status} ->
{:error, [output]}
end
end
defp compile_in_docker(target) do
tag = "rambo/" <> target
build = ["build", "--tag", tag, "--file", "Dockerfile." <> target, "."]
with {_output, 0} <- System.cmd("docker", build, cd: @compile_priv_dir),
{_output, 0} <- System.cmd("docker", ["run", "--volume", @compile_priv_dir <> ":/app", tag]) do
move_executable(target)
:ok
else
{output, _exit_status} -> {:error, [output]}
end
end
defp move_executable(target) do
target_executable =
case target do
:custom -> "target/release/rambo"
@windows -> "target/#{@windows}/release/rambo.exe"
target -> "target/#{target}/release/rambo"
end
source = Path.join(@compile_priv_dir, target_executable)
destination = Path.join(@compile_priv_dir, @filenames[target])
File.rename!(source, destination)
end
end