Umbrella Projects

实际上有时工程项目会变得很大. Mix 构建工具可以让我们将代码划分成多个程序, 使得项目变大的时候更易于管理.

介绍

创建一个 umbrella project 就像我们创建 Mix project 时一样, 只是多传入了 --umbrella 标志. 下面的例子中我们将创建一个机器学习的命令行工具. 你问为什么是一个机器学习工具? 为什么不呢? 它们将由一些学习算法和通用函数组成.

$ mix new machine_learning_toolkit --umbrella
* creating .gitignore
* creating README.md
* creating mix.exs
* creating apps
* creating config
* creating config/config.exs
Your umbrella project was created successfully.
Inside your project, you will find an apps/ directory
where you can create and host many apps:
cd machine_learning_toolkit
cd apps
mix new my_app
Commands like "mix compile" and "mix test" when executed
in the umbrella project root will automatically run
for each application in the apps/ directory.

正如你在 shell 命令中看到的, Mix 为我们创建了一个项目的框架, 并有两个目录:

  • apps/ - 我们子项目所在的地方

  • config/ - 我们 umbrella 项目配置文件所在的地方

子项目

让我们切换到项目的 machine_learning_toolkit/apps 目录并用 Mix 创建三个普通的项目:

$ mix new utilities
* creating README.md
* creating .gitignore
* creating mix.exs
* creating config
* creating config/config.exs
* creating lib
* creating lib/utilities.ex
* creating test
* creating test/test_helper.exs
* creating test/utilities_test.exs
Your Mix project was created successfully.
You can use "mix" to compile it, test it, and more:
cd utilities
mix test
Run "mix help" for more commands.
$ mix new datasets
* creating README.md
* creating .gitignore
* creating mix.exs
* creating config
* creating config/config.exs
* creating lib
* creating lib/datasets.ex
* creating test
* creating test/test_helper.exs
* creating test/datasets_test.exs
Your Mix project was created successfully.
You can use "mix" to compile it, test it, and more:
cd datasets
mix test
Run "mix help" for more commands.
$ mix new svm
* creating README.md
* creating .gitignore
* creating mix.exs
* creating config
* creating config/config.exs
* creating lib
* creating lib/svm.ex
* creating test
* creating test/test_helper.exs
* creating test/svm_test.exs
Your Mix project was created successfully.
You can use "mix" to compile it, test it, and more:
cd svm
mix test
Run "mix help" for more commands.

现在我们项目中的文件结构应该像这样:

$ tree
.
├── README.md
├── apps
│ ├── datasets
│ │ ├── README.md
│ │ ├── config
│ │ │ └── config.exs
│ │ ├── lib
│ │ │ └── datasets.ex
│ │ ├── mix.exs
│ │ └── test
│ │ ├── datasets_test.exs
│ │ └── test_helper.exs
│ ├── svm
│ │ ├── README.md
│ │ ├── config
│ │ │ └── config.exs
│ │ ├── lib
│ │ │ └── svm.ex
│ │ ├── mix.exs
│ │ └── test
│ │ ├── svm_test.exs
│ │ └── test_helper.exs
│ └── utilities
│ ├── README.md
│ ├── config
│ │ └── config.exs
│ ├── lib
│ │ └── utilities.ex
│ ├── mix.exs
│ └── test
│ ├── test_helper.exs
│ └── utilities_test.exs
├── config
│ └── config.exs
└── mix.exs

当切回 umbrella 项目的根目录时, 可以发现我们可以调用所有常见的命令, 比如: compile(编译). 所有的子项目也是普通的 application,你可以切到他们的目录和通常项目一样做 Mix 可以做的事.

$ mix compile
==> svm
Compiled lib/svm.ex
Generated svm app
==> datasets
Compiled lib/datasets.ex
Generated datasets app
==> utilities
Compiled lib/utilities.ex
Generated utilities app
Consolidated List.Chars
Consolidated Collectable
Consolidated String.Chars
Consolidated Enumerable
Consolidated IEx.Info
Consolidated Inspect

IEx

你也许认为和 umbrella 项目在 IEx 中交互会有些区别. 不管你信不信, 你猜错了! 当我们切到顶层目录并用 iex -S mix 启动 IEx, 我们可以正常的和所有项目进行交互. 让我们改变一下 apps/datasets/lib/datasets.ex 的内容来举个例子:

defmodule Datasets do
def hello do
IO.puts("Hello, I'm the datasets")
end
end
$ iex -S mix
Erlang/OTP {{ site.erlang.OTP }} [erts-{{ site.erlang.erts }}] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
==> datasets
Compiled lib/datasets.ex
Consolidated List.Chars
Consolidated Collectable
Consolidated String.Chars
Consolidated Enumerable
Consolidated IEx.Info
Consolidated Inspect
Interactive Elixir ({{ site.elixir.version }}) - press Ctrl+C to exit (type h() ENTER for help)
iex> Datasets.hello
:world