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

Posted

技术标签:

【中文标题】如何重新编译 Elixir 项目并从 iex 中重新加载它?【英文标题】:How do I recompile an Elixir project and reload it from within iex? 【发布时间】:2016-07-29 03:44:22 【问题描述】:

我目前正在通过 elixir-lang 网站上的 OTP 和 mix 教程学习 Elixir,但我在找出如何从 shell 中重新编译和重新加载项目时遇到了麻烦。

在 Erlang 中,我会执行 make:all([load]),它会编译并加载发生的任何更改。但是,在 iex 中总是说 :up_to_date,这确实有道理,因为 Elixir 使用 mix 来满足其编译需求。

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

【问题讨论】:

你在iex 中尝试过r/1 吗?请注意,您可以通过调用h() 来调用iex 中的帮助。看看其中一些是否对您有帮助。 我不知道r/1,但这仍然不等同。我必须手动输入我已更新代码的每个模块,因为make:all([load]) 将自动检测更新的模块并重新编译/重新加载它们。 也许您正在寻找与***.com/questions/32540703/… 和groups.google.com/forum/#!topic/elixir-lang-talk/uU8K2NJAE70 相关的内容?这似乎与那些重复。 我也想知道,我决定开发lettuce。它是一个生成服务器,可以在不离开 IEx 的情况下监视您的文件并为您重新编译项目。看看????! 【参考方案1】:

您可以使用IEx.Helpers.recompile/0 函数。

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

此帮助程序仅在 IEx 与 Mix 项目一起启动时才有效,因为 例如,iex -S mix。在编译代码之前,它会停止 当前应用程序,然后重新启动它。停止 应用程序是必需的,因此监督树中的进程不会 当代码多次升级而没有经过 适当的热代码交换机制。

mix.exs 或配置文件的更改将不会被此拾取 助手,仅更改来源。重新启动外壳和混合是 在这种情况下需要。

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

注意:此功能是实验性的,可能会在未来移除 发布。

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

【讨论】:

c("filename.ex") 的工作方式是否与@Dogbert 相同?只是好奇。 @OnorioCatenacci 不,它只是重新编译一个文件,句号。 IEx.Helpers.recompile/0 将使正在运行的进程崩溃。它还会通过不加载失败的模块来忽略编译错误。这使得它无法用于实时编码。 这个函数的行为已经改变——它不再重新启动应用程序。此外,文档已移动,现在为 here。【参考方案2】:

我发现@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 并且所有内容都是热重载的,无需重新启动应用程序。

【讨论】:

这在 1.5 版中不再有效。我得到[:noop, :noop]【参考方案3】:

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,项目将在该源文件丢失和卸载的情况下进行编译。

【讨论】:

以上是关于如何重新编译 Elixir 项目并从 iex 中重新加载它?的主要内容,如果未能解决你的问题,请参考以下文章

Elixir IEX在显示提示之前停止,并且不接受输入

Elixir IEx shell,如何突破当前的“接收”块

Elixir - 从命令行运行时记录器输出是彩色的,从 iex 运行时不是这样

将 iex shell 附加到正在运行的 elixir 应用程序

无法在 Windows 命令提示符或 git bash 中运行 iex

为输入 iex shell 着色