如何重新编译Elixir项目并从iex中重新加载?

Kal*_*exx 53 elixir-mix elixir

我目前正在学习Elixir,通过在elixir-lang网站上浏览OTP和混合教程,我很难找到如何从shell中重新编译和重新加载项目.

在Erlang中我会这样做make:all([load]),它会编译并加载发生的任何更改.然而,iex总是说:up_to_date,这确实有意义,因为Elixir使用mix来满足它的编译需求.

我在iex中找不到任何等价物.

Dog*_*ert 87

你可以使用这个IEx.Helpers.recompile/0功能.

重新编译当前的Mix应用程序.

例如,只有在使用Mix项目启动IEx时,此助手才有效iex -S mix.在编译代码之前,它将停止当前应用程序,然后再次启动它.需要停止应用程序,因此当代码多次升级而不通过正确的热代码交换机制时,监督树中的进程不会崩溃.

mix.exs此助手不会获取对配置文件的更改,只会更改源.在这种情况下,需要重新启动shell和Mix.

如果要重新加载单个模块,请考虑使用r ModuleName .

注意:此功能是实验性的,可能会在即将发布的版本中删除.

来自https://github.com/elixir-lang/elixir/blob/v1.2.4/lib/iex/lib/iex/helpers.ex#L56-L93

  • `c("filename.ex")`的工作方式与@Dogbert相同吗?只是好奇. (2认同)

Van*_*s S 21

2017年2月26日:

要在运行的灵丹妙药系统中热负载组件,出现问题的可能性最小,请使用:

case c(filename_ex, :in_memory) do
    [] -> :ignore
    [mod|_] -> r(mod)
end
Run Code Online (Sandbox Code Playgroud)

原始答案:

在elixir 1.3.0中,重新编译不再重新启动应用程序.因此,检查是否有任何源更改和hotload的正确方法是:

iex> recompile()
Run Code Online (Sandbox Code Playgroud)

注意:我想补充一点,由于在重新编译期间删除模块的问题,如果你有一个带有state_timeout的gen_statem等飞行消息,那么在重新编译时很可能会崩溃进程.

注意2:如果在源文件中出错,则使用recompile/0,项目将在缺少和卸载该源文件的情况下进行编译.


Kal*_*exx 7

我发现@ Dogbert的答案的一个缺点是它完全停止并重新启动应用程序.虽然这在理论上是可以的但它在我当前的项目中失败了,因为我的项目依赖于Ranch,但一切都没有得到正确的停止.这意味着当它尝试重新启动它失败的项目时会发生故障,因为套接字已经在使用中.

简而言之,我查看了帮助程序的代码并将以下函数添加到我的模块中:

  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  
Run Code Online (Sandbox Code Playgroud)

现在我可以进入MyApp.recompile并且在没有重新启动应用程序的情况下热重新加载所有内容.