web-dev-qa-db-ja.com

Elixirプロジェクトを再コンパイルし、iex内からリロードするにはどうすればよいですか?

現在、エリクサーのウェブサイトでOTPとミックスチュートリアルを試してElixirを学んでいますが、シェル内からプロジェクトを再コンパイルしてリロードする方法を見つけるのに苦労しています。

Erlangではmake:all([load])を実行し、発生した変更をコンパイルしてロードします。ただし、iexでは常に:up_to_date、これは理にかなっています。Elixirはコンパイルのニーズにmixを使用しているためです。

Iex内で同等のものが見つかりません。

49
KallDrexx

IEx.Helpers.recompile/0 関数を使用できます。

現在のMixアプリケーションを再コンパイルします。

このヘルパーは、IExがiex -S mixなどのMixプロジェクトで開始された場合にのみ機能します。コードをコンパイルする前に、現在のアプリケーションを停止し、その後再び起動します。適切なホットコードスワッピングメカニズムを経由せずにコードを複数回アップグレードしても、監視ツリー内のプロセスがクラッシュしないように、アプリケーションを停止する必要があります。

mix.exsまたは構成ファイルへの変更は、このヘルパーによってピックアップされず、ソースへの変更のみがピックアップされます。このような場合、シェルとミックスの再起動が必要です。

単一のモジュールをリロードする場合は、代わりにr ModuleNameの使用を検討してください。

注:この機能は実験的なものであり、今後のリリースで削除される可能性があります。

から https://github.com/elixir-lang/elixir/blob/v1.2.4/lib/iex/lib/iex/helpers.ex#L56-L9

82
Dogbert

2017年2月26日:

何か問題が発生する可能性が最も低い実行中のエリキシルシステムでコンポーネントをホットロードするには:

case c(filename_ex, :in_memory) do
    [] -> :ignore
    [mod|_] -> r(mod)
end

元の回答:

Elixir 1.3.0では、recompileはアプリケーションを再起動しません。したがって、ソースが変更され、ホットロードがあったかどうかを確認する正しい方法は次のとおりです。

iex> recompile()

注:再コンパイル中のモジュールの削除の問題により、state_timeoutを含むgen_statemのような飛行中のメッセージがある場合、再コンパイルの実行中にプロセスがクラッシュする可能性が高いことを追加します。

注2:ソースファイルにエラーを作成した場合、recompile/0を使用すると、プロジェクトはコンパイルされ、そのソースファイルが失われてアンロードされます。

20
Vans S

私が見つけた@Dogbertの答えの欠点は、アプリケーションの完全な停止と再起動を行うことです。これは理論上は問題ありませんが、私のプロジェクトは牧場に依存しているため、現在のプロジェクトでは失敗しましたが、すべてが適切に停止しませんでした。これは、ソケットがすでに使用されていたために失敗したプロジェクトを再起動しようとしたときに問題が発生したことを意味していました。

簡単に言えば、ヘルパーのコードを見て、モジュールに次の機能を追加しました。

  def recompile() do
    Mix.Task.reenable("app.start")
    Mix.Task.reenable("compile")
    Mix.Task.reenable("compile.all")
    compilers = Mix.compilers
    Enum.each compilers, &Mix.Task.reenable("compile.#{&1}")
    Mix.Task.run("compile.all")
  end  

これでMyApp.recompileと入力でき、アプリケーションを再起動せずにすべてがホットリロードされます。

6
KallDrexx