11
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[連載] Erlangプロジェクトでもmixを使うべきか(2)

Last updated at Posted at 2015-05-04

はじめに

前回の記事rebarでやったことを今度はElixirのビルドツールmixを使ってやってみましょう。

mixにおける依存アプリケーション・バージョン衝突問題の回避

ElixirはErlangのアプリケーションをそのまま読み込めますので前回の記事で使用したErlangのサブアプリケーションを今度はElixirプロジェクトが必要としているという場面を想定しましよう。サブ・アプリケーションがErlangなのかElixirなのかは本質的に重要ではありません。

https://github.com/massn/sample_main_elixir/tree/v0.0.1

に空のElixirプロジェクトを組んでみました。Elixirはビルド時にビルドツールのmixやテストツールやら開発に必要なもろもろが既に組み込まれており、ほとんどの開発者がこのプロジェクトと同じようなフォーマットで開発を進めていくことと思います。
Erlang/rebarプロジェクトのrebar.configにあたるものが、Elixir/mixではmix.exsにあたります。

mix.exs
defmodule SampleMainElixir.Mixfile do
  use Mix.Project

  def project do
    [app: :sample_main_elixir,
     version: "0.0.1",
     elixir: "~> 1.0",
     deps: deps]
  end

  defp deps do
    [{:sample_sub1, git: "https://github.com/massn/sample_sub1.git", tag: "v0.0.1"},
     {:sample_sub2, git: "https://github.com/massn/sample_sub2.git", tag: "v0.0.1"}]
  end
end

depsという関数が返すリストに依存アプリケーションが書かれています。書き方が少々Erlangと違いますがなんとなくわかると思います(糖衣構文なども含まれていますが、表現しているのはErlangと互換性のあるデータ構造です)。依存アプリケーションをダウンロードしてみましょう。

$ ./mix deps.get

このコマンドでmix.lockというファイルにダウンロードされるべき全てのアプリケーションのバージョンが書き込まれ、同時にダウンロードが行われます。RubyでGemパッケージを使うときのGemfile.lockのようなものです。mix.lockファイルを見てみましょう。

mix.lock
%{"cowboy": {:git, "https://github.com/ninenines/cowboy.git", "ee3ad5e51005b453230804036e092e1d2ceebe4f", [ref: "0.10.0"]},
  "cowlib": {:git, "git://github.com/extend/cowlib.git", "e2ffefe828b918486e2cd76e44c54ae9b62c616e", [ref: "0.6.2"]},
  "ranch": {:git, "git://github.com/extend/ranch.git", "3189ef2d47843945efc96c224963380462c33d40", [ref: "0.10.0"]},
  "sample_sub1": {:git, "https://github.com/massn/sample_sub1.git", "1700f7e6d4d708351a2c02274643646808e35911", [tag: "v0.0.1"]},
  "sample_sub2": {:git, "https://github.com/massn/sample_sub2.git", "0fe69055e0da389d4b28257e4db44495d1a3e641", [tag: "v0.0.1"]}}

すべての依存アプリケーションの使うべきバージョン、さらにはコミットIDまで列挙されてますね。mix.lockファイルはmix.exsを元にしており、その時点でそこから推測できるアプリケーション情報を持っています。例えばあるアプリケーションのmasterブランチがmix.exsに指定されていると、そのときのmasterブランチのコミットIDが記載されるわけです。このロックファイルをgit管理することで開発者が使った依存アプリケーションの環境をそのまま再現することが可能になります。
ところで前回問題にしたcowboyはどのバージョンが使われているのでしょう?sample_sub2が要求する0.10.0です。うーん、今度はdepsが返すリストの後ろの方が優先順位が高いようです。。。わかりにくい。できればリストの順番なんか気にしたくない。
ここで、mix deps.checkというコマンドを使ってみましょう。

$ ./mix deps.check
Unchecked dependencies for environment dev:
* cowboy (https://github.com/ninenines/cowboy.git)
  different specs were given for the cowboy app:

  > In deps/sample_sub2/rebar.config:
    {:cowboy, ~r/.*/, [git: "https://github.com/ninenines/cowboy.git", ref: "0.10.0"]}

  > In deps/sample_sub1/rebar.config:
    {:cowboy, ~r/.*/, [git: "https://github.com/ninenines/cowboy.git", ref: "0.8.0"]}

  Ensure they match or specify one of the above in your SampleMainElixir.Mixfile deps and set `override: true`

おお。

「deps内のアプリケーションが同一アプリケーションの別バージョンを要求しているよ。そいつらのバージョンを合わせるか、depsoverride: trueをセットしてアプリケーションを要求してね」

というありがたいアドバイスが。正しくその通りです。mix.exsを以下のように修正しましょう( https://github.com/massn/sample_main_elixir/tree/v0.0.2 )。

mix.exs
defmodule SampleMainElixir.Mixfile do
  use Mix.Project

  def project do
     [app: :sample_main_elixir,
      version: "0.0.1",
      elixir: "~> 1.0",
      deps: deps]
   end

  defp deps do
     [{:cowboy, git: "https://github.com/ninenines/cowboy.git", ref: "0.10.0", override: true},
      {:sample_sub1, git: "https://github.com/massn/sample_sub1.git", tag: "v0.0.1"},
      {:sample_sub2, git: "https://github.com/massn/sample_sub2.git", tag: "v0.0.1"}]
    end
end

バージョン競合が起きているアプリケーションについては、明示的にこのバージョンを使用しろと書くわけです。override: trueを書かないと再びmix deps.checkでエラーが出てしまうのでお忘れなく。これで./mix deps.checkをするとエラーが出ず、コンパイルが始まります。

まとめ

mixでの開発において依存アプリケーションのバージョン指定については以下のような指針を設けるのがよさそうです。

全ての依存アプリケーションにおいてバージョン衝突があるかないかをmix deps.checkコマンドで確認する

バージョン衝突が起きた場合は、バージョンをそろえるか、一番上の階層の(依存アプリケーションがmix.exsを持つこともある)mix.exsに使用するアプリケーションのバージョンを明示する(override: trueを忘れずに)

生成されたmix.lockファイルをgit管理などして、全ての使用アプリケーションのバージョンを明示する

これはrebarよりいい感じですね。

つづく

11
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?