我目前正在通过 elixir-lang 网站上的 OTP 和混合教程来学习 Elixir,但我在找出如何从 shell 中重新编译和重新加载项目时遇到了麻烦。
在 Erlang 我会这样做make:all([load])
,它会编译并加载发生的任何更改。然而,iex
总是说:up_to_date
,这确实是有道理的,因为 Elixir 使用 mix 来满足它的编译需求。
我在 iex 中找不到任何等价物。
我目前正在通过 elixir-lang 网站上的 OTP 和混合教程来学习 Elixir,但我在找出如何从 shell 中重新编译和重新加载项目时遇到了麻烦。
在 Erlang 我会这样做make:all([load])
,它会编译并加载发生的任何更改。然而,iex
总是说:up_to_date
,这确实是有道理的,因为 Elixir 使用 mix 来满足它的编译需求。
我在 iex 中找不到任何等价物。
您可以使用该IEx.Helpers.recompile/0
功能。
重新编译当前的 Mix 应用程序。
此帮助程序仅在 IEx 与 Mix 项目一起启动时才有效,例如
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
2017 年 2 月 26 日:
要在运行中的 Elixir 系统中热加载组件,并且出错的可能性最低,请使用:
case c(filename_ex, :in_memory) do
[] -> :ignore
[mod|_] -> r(mod)
end
原答案:
在 elixir 1.3.0 中重新编译不再重新启动应用程序。因此,检查是否有任何源更改和热加载的正确方法是:
iex> recompile()
注意:我想补充一点,由于在重新编译期间删除模块的问题,如果您有诸如带有 state_timeout 的 gen_statem 之类的飞行消息,那么您很可能会在重新编译发生时崩溃进程。
注意 2:如果您在源文件中出错,则使用 recompile/0,项目将在该源文件丢失和卸载的情况下进行编译。
我发现@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
现在我可以进入MyApp.recompile
,一切都被热重新加载,而无需重新启动应用程序。