实际上有时工程项目会变得很大. 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.exsYour umbrella project was created successfully.Inside your project, you will find an apps/ directorywhere you can create and host many apps:cd machine_learning_toolkitcd appsmix new my_appCommands like "mix compile" and "mix test" when executedin the umbrella project root will automatically runfor 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.exsYour Mix project was created successfully.You can use "mix" to compile it, test it, and more:cd utilitiesmix testRun "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.exsYour Mix project was created successfully.You can use "mix" to compile it, test it, and more:cd datasetsmix testRun "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.exsYour Mix project was created successfully.You can use "mix" to compile it, test it, and more:cd svmmix testRun "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==> svmCompiled lib/svm.exGenerated svm app==> datasetsCompiled lib/datasets.exGenerated datasets app==> utilitiesCompiled lib/utilities.exGenerated utilities appConsolidated List.CharsConsolidated CollectableConsolidated String.CharsConsolidated EnumerableConsolidated IEx.InfoConsolidated Inspect
你也许认为和 umbrella 项目在 IEx 中交互会有些区别. 不管你信不信, 你猜错了! 当我们切到顶层目录并用 iex -S mix
启动 IEx, 我们可以正常的和所有项目进行交互. 让我们改变一下 apps/datasets/lib/datasets.ex
的内容来举个例子:
defmodule Datasets dodef hello doIO.puts("Hello, I'm the datasets")endend
$ iex -S mixErlang/OTP {{ site.erlang.OTP }} [erts-{{ site.erlang.erts }}] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]==> datasetsCompiled lib/datasets.exConsolidated List.CharsConsolidated CollectableConsolidated String.CharsConsolidated EnumerableConsolidated IEx.InfoConsolidated InspectInteractive Elixir ({{ site.elixir.version }}) - press Ctrl+C to exit (type h() ENTER for help)iex> Datasets.hello:world