結論
-
mix compile
は複数のcompile.*
タスクから成る。 - 自前の
compile.hogehoge
タスクもcompile
タスクに組み込むことができる。 - コンパイルのタイミングは
mix.exs
で指定する。
Code.require_file "lib/mix/tasks/compile.hogehoge.ex"
defmodule MyAwesomeApp.Mixfile do
use Mix.Project
def project do
[app: :my_awesome_app,
version: "0.0.1",
elixir: "~> 1.0",
compilers: [:hogehoge, :elixir, :app],
deps: deps]
end
# 略
end
説明
何したい
例えばNIFなど、Cで書いた関数を使うElixirモジュールを作りたいとする。そのElixirモジュールはCの関数に依存するわけなので、Elixirモジュールのコンパイルの前にはCのコンパイルが済んでいてほしい。自分でやるなら勝手にどうぞって感じだけど、他人にライブラリとして提供する場合はそうもいかない。mix deps.compile
のタイミングで、Cのソースもコンパイルしたい。
どうする
mix deps.compile
mix deps.compile
は、依存するライブラリを全てコンパイルする。どうやってコンパイルするかは、そのライブラリが持つファイルによって決まる。
ファイル | コマンド | 優先度 |
---|---|---|
mix.exs | mix compile |
高 |
rebar.config | rebar compile |
↑ |
Makefile.win | nmake /F Makefile.win |
↓ |
Makefile | make |
低 |
Makefileを置いてmake
をさせたいけれど、Mixプロジェクトはmix compile
されてしまう。
mix compile
mix compile
は複数のタスクを実行する。ここにCをコンパイルするタスクを忍ばせる。タスクはcompile.hogehoge
のように、compile
名前空間になければならない。どのタイミングで実行するかはmix.exs
のproject/0
で指定する。デフォルトのcompilers
はMix.compilers
で取得できるので、それらの前に付ける方法がGithubではよく見られる(特にPhoenixプロジェクト)。
defmodule Mix.Tasks.Compile.Hogehoge do
use Mix.Task
def run(_), do: Mix.shell.cmd "make"
end
def MyAwesomeApp.Mixfile do
def project do
[app: :my_awesome_app,
version: "0.0.1",
elixir: "~> 1.0",
compilers: [:hogehoge] ++ Mix.compilers,
deps: deps]
end
end
これでmix compile
時にmake
が走る。ライブラリとして提供した際にもmix deps.compile
のときにmake
が走ってNIFが使えるようになる。compile
名前空間内なのでコンパイル以外の処理をするのはどうかなー感があるが、Cのコンパイルに限らず任意の処理が可能。