Posted at

mix compile中に任意のコンパイル処理をする

More than 3 years have passed since last update.


結論



  • 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.exsproject/0で指定する。デフォルトのcompilersMix.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のコンパイルに限らず任意の処理が可能。