运行 混合任意命令

Running arbitrary commands in mix

我在 proto/*.proto 中有一些协议缓冲区定义。我当前的 Makefile-based 构建系统将它们中的每一个都编译成一个 Erlang 模块和 header,然后编译成一个 self-descriptor(作为一个 .pb 文件),然后将描述符嵌入为一个 BEAM模块:

foo.proto -> foo_pb.erl, foo_pb.hrl
          -> foo.pb -> foo_pb_desc.beam

我已经实施了 mix_protobuffs 任务来完成第一步,foo.proto -> foo.pb part-step。

我还得到了将任意文件嵌入 Erlang 模块的相关代码——灵感来自 this answer——但我想知道将其集成到我的 [=34] 中的推荐方法=]构建过程。

同样,我还有一些其他文件需要处理然后嵌入,这表明我不应该让 mix_protobuffs 任务知道嵌入。

所以我想我在问:有没有办法混合 运行 任意命令 pre/post 另一个任务?

通常的方法是定义您自己的编译器。为此,您要在 Mix.Task.Compiler 命名空间 中创建一个模块来实现 Mix.Task.Compiler 行为。此外,您的 mix.exsproject/0 函数应更新为 return 您的新编译器。像下面这样就可以了。

defmodule Mix.Tasks.Compile.Protobufs do
  use Mix.Task.Compiler

  @recursive true

  @impl Mix.Task.Compiler
  def run(argv) do
    # do your compilation, possibly with System.cmd/3
    :ok
  end
end

并且在您的项目文件中:

def project do
  [
    compilers: Mix.compilers() ++ [:protobufs],
    # ...
  ]
end

您还可以从您自己的任务中调用任何现有的 mix 任务,例如 Mix.Tasks.Run.run(args)