如果您查看mix.exs
文件,您会注意到:
use Mix.Project
此file现在包含:
@doc false
defmacro __using__(_) do
quote do
@after_compile Mix.Project
end
end
# Invoked after each Mix.Project is compiled.
@doc false
def __after_compile__(env,_binary) do
push(env.module,env.file)
end
@after_compile
是在elixir/kernel.ex中定义的宏,即使它是一种奇怪的形式,也由__using__
从mix.exs
调用。由于您无法在模块外部调用宏,因此需要在mix.exs
文件中包含一个模块。
为了更清楚地说明这一点,让我们尝试删除mix.exs
中的模块并运行项目:
* (ArgumentError) cannot invoke @/1 outside module
(elixir) lib/kernel.ex:5230: Kernel.assert_module_scope/3
(elixir) expanding macro: Kernel.@/1
mix.exs:2: (file)
(mix) expanding macro: Mix.Project.__using__/1
mix.exs:2: (file)
(elixir) expanding macro: Kernel.use/1
mix.exs:2: (file)
因此,您的问题的答案是,如果没有模块,则无法调用钩子@after_compile
,因为钩子本身就是宏。钩子最有可能用于在所有文件编译之后自动加载项目。
PS:push/3
函数调用一个有趣的模块函数:
Mix.ProjectStack.push(原子,配置,文件)
如果查看ProjectStack模块的源代码,您会发现它是基于Agent的状态机。因此,基本上所有混合项目都被压入堆栈,并且可以检查它们的名称中是否存在重复项。
本文链接:https://www.f2er.com/3164591.html