Elixir 脚本递归加载文件夹中的所有模块

Elixir script load all modules in folder recursivelly

我想在特定文件夹中递归地编译和加载所有模块。 我知道我可以用 Mix 项目做到这一点

iex -S mix run

这将加载 lib/ 目录中的所有文件。

但是我希望在非 Mix 脚本中有相同的行为 - 如果可能的话以编程方式进行。 类似于 Code.compile_all("directory/")
有这样的API吗?

我不确定在 Elixir 中是否有内置的方法来执行此操作,但是您可以使用 Erlang 中的 filelib:fold_files/5 之类的方法来获得相同的结果。

:filelib.fold_files "directory/", "\.ex$", true, &Code.load_file/1, []

澄清一下:Mix 不会加载 lib/ 中的文件,如果需要它会编译它们,然后使用编译后的字节码(无需再次执行整个文件)。

您可以通过调用 Code.require_file/1Code.load_file/1 加载目录中的任何文件,但这不会在磁盘中生成任何工件。如果您稍后调用 Code.require_file/1,将再次评估相同的文件,这可能需要一些时间。编译的思路正是让你不用每次都付出这个代价。

话虽如此,让我们直接回答你的问题。

  1. 加载目录中所有内容的方法是:

    dir
    |> Path.join("**/*.exs")
    |> Path.wildcard()
    |> Enum.map(&Code.require_file/1)
    
  2. 如果要编译它们,使用:

    dir
    |> Path.join("**/*.ex")
    |> Path.wildcard()
    |> Kernel.ParallelCompiler.files_to_path("path/for/beam/files")
    
  3. 如果你只想在项目的上下文中编译另一个目录(有 mix.exs 等等),你可以在 [=16] 中提供你想要混合的任何目录=]:

    elixirc_paths: ["lib", "my/other/path"]
    

就是这样。