defmodule MBU.BuildTask do @moduledoc """ BuildTask contains the macros that are used for making the tasks look nicer. """ @doc """ Sets up the necessary things for a build task. Each build task should have `use MBU.BuildTask` at its beginning. BuildTask automatically imports Mix.Task and Logger so they don't need to be added into the task itself. The following options may be passed to the use clause: - `:auto_path`: Set to `true` to autogenerate an `out_path/0` function for this task. Default: `false`. Overrides the `:auto_paths` config. - `:create_out_path`: Set to `true` to create the output path specified by `out_path/0` when the task is started. Default: `false`. Overrides the `:create_out_paths` config. """ defmacro __using__(opts \\ []) do quote do use Mix.Task require Logger import MBU.BuildTask # Dependencies of the task that will be automatically run before it @deps [] @create_out_path Keyword.get(unquote(opts), :create_out_path, nil) auto_path = Keyword.get(unquote(opts), :auto_path, nil) if auto_path || (Application.get_env(:mbu, :auto_paths, false) and auto_path == nil) do def out_path() do Path.join([tmp_path(), Mix.Task.task_name(__MODULE__)]) end defp tmp_path() do # Get temporary directory or raise error case Application.get_env(:mbu, :tmp_path) do nil -> raise "MBU must be configured with a directory to put temporary files in if automatic " "directory handling is used! Use the `:tmp_path` key to set a desired path." path -> path end end end end end @doc """ Replacement for Mix.Task's run/1, used similarly. Code inside will be run when the task is called, with @deps being run first unless `deps: false` is given in the arguments. """ defmacro task(args, do: block) do quote do def run(unquote(args) = mbu_buildtask_args) do task = Mix.Task.task_name(__MODULE__) Logger.info("[#{task}] Started") if @create_out_path || (Application.get_env(:mbu, :create_out_paths, false) and @create_out_path == nil) do op = apply(__MODULE__, :out_path, []) Logger.info("[#{task}] Creating output path #{op}...") :ok = File.mkdir_p!(op) end if Keyword.get(mbu_buildtask_args, :deps, true) and not Enum.empty?(@deps) do MBU.TaskUtils.run_tasks(@deps) end unquote(block) Logger.info("[#{task}] Finished") end end end end