Umbrella Projects

Some contents of this translation may be outdated.
Several patches were applied to the original lesson since the last update.

实际上有时工程项目会变得很大. 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 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 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 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 22.0 [erts-10.5.3] [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 (1.10.1) - press Ctrl+C to exit (type h() ENTER for help)

iex> Datasets.hello
:world
Caught a mistake or want to contribute to the lesson? Edit this page on GitHub!