我的有道云 http://note.youdao.com/noteshare ... 1F0BA2902252E500267 
#### 包和依赖项(Packages and dependencies) 
##### 查找包(Searching packages) 
``` 
make search 
make search | less 
``` 
查看所有能使用的包 
``` 
make search q=cowboy 
``` 
##### 添加依赖包( Adding dependencies to your project) 
``` 
DEPS = cowboy 
``` 
加了这个参数,erlang.mk会保证cowboy能运行在shell、run、tests命令的时候 
 
如果依赖包不用在erlang运行的时候跑的话,那就把它设置为BUILD_DEPS就行了,这样就只有构建的时候会用到 
``` 
BUILD_DEPS = erlando 
``` 
或者你直接依赖c项目,构建nif 
``` 
BUILD_DEPS = leveldb 
dep_leveldb = git https://github.com/basho/leveldb 2.1.3 
``` 
这样做,依赖会比你的应用先被构建,你就可以把它生成的共享文件作为你构建过程中的一部分 
 
本地依赖比较容易理解,就是otp内部项目的依赖: 
``` 
LOCAL_DEPS = crypto 
``` 
 
还有专为测试用的TEST_DEPS,只有当测试的时候才会运行 
``` 
TEST_DEPS = ct_helper 
dep_ct_helper = git https://github.com/ninenines/ct_helper master 
``` 
 
文档专用 
``` 
DOC_DEPS = recon 
``` 
生成文档的时候会被用到的依赖项 
 
shell专用依赖项 
``` 
SHELL_DEPS = tddreloader 
``` 
用户执行make shell命令的时候会用到的依赖 
##### 修改依赖项或者版本(Modifying the dependency source or version) 
当我们用到cowboy,但是erlang.mk的版本不是我想要的,这时候就可以用```dep_$(DEP_NAME)_commit```变量 
``` 
DEPS = cowoby 
dep_cowboy_commit = 2.0.0-pre.2 
``` 
这个办法只改变版本号,依赖项还是由erlang.mk决定的,你要从其它途径获得依赖项,可以用```dep_$(DEP_NAME)```参数 
``` 
DEPS = cowoby 
dep_cowoby = git https://github.com/essen/cowboy 2.0.0-pre.2 
``` 
这样做就会从你指定的git上获取依赖项 
 
##### 获取方式(Fetch methods) 
名 | 格式 | 描述 
--- | --- | --- 
git | git repo commit | 从git克隆或者checkout指定的版本 
git-submodule | git-submodule | 初始化或更新git的子模块 
hg | hg repo commit | 克隆Mercurial存储库并更新到给定版本 
svn | svn repo | checkout指定的svn库 
cp | cp /path/to/repo | 递归复制本地目录的文件 
ln | ln path/to/repo | 软(符号)链接到一个路径 
hex | hex version | 从hex.pm下载指定项目版本 
fail | N/A | 总是失败,内部使用 
legacy | N/A | erlang.mk遗留的提取程序,内部使用 
 
git和hg的方式很相似,都有代码仓库和提交版本,可以用提交记录,标签或者分支来获取依赖 
``` 
dep_cowboy = git https://github.com/ninenines/cowboy 2.0.0-pre.2 
dep_ehsa = hg https://bitbucket.org/a12n/ehsa 4.0.3 
``` 
但是git可以更新或者添加子模块的依赖 
``` 
dep_cowboy = git-submodule 
``` 
svn的方式只有一个版本库,它通过路径来指定项 
``` 
dep_ex1 = svn https://example.com/svn/trunk/project/ex1 
``` 
也可以获取单独的示例项目 
``` 
dep_ex2 = svn svn://example.com/svn/branches/erlang-proj/ex2@264 
``` 
直接本地复制的获取依赖项方式 
``` 
dep_cowboy = cp $(HOME)/ninenines/cowboy 
``` 
hex方式 
``` 
dep_cowboy = hex 1.0.3 
``` 
##### 自定义提取方法(Custom fetch methods) 
```dep_fetch_(METHOD)``` 变量用来定义提取方法,只要你创建了 ```$(DEPS_DIR)/$(call dep_name, $1)```文件夹,你在这个变量中做任何事 
``` 
define dep_fetch_git 
    git clone -q -n -- $(call dep_repo,$1) $(DEPS_DIR)/$(call dep_name,$1); \ 
    cd $(DEPS_DIR)/$(call dep_name,$1) && git checkout -q $(call dep_commit,$1); 
endef 
``` 
获取方式必须在你使用之前被定义 
 
##### 依赖项的获取和构建(How deps are fetched and built) 
获取构建顺序大概如下 
1. 为应用拉取所有依赖项 
2. 构建第一个依赖项 
3. 构建第N个依赖项 
4. 构建最后依赖项 
 
每次构建后,都是相同的方式递归进行 
 
同一个应用拉取依赖项的时候并不一定按顺序获取依赖,因为不可能有重复的依赖项存在 
如果不同应用之间有相同依赖项被拉取,这时以先到者为准,冲突什么的不存在的 
 
还要注意,拉取和构建不是并行的,先拉取所有依赖项之后才开始构建 
##### 只拉取和只列出依赖项(Fetching and listing dependencies only) 
只拉取依赖项 
``` 
make fetch-deps 
``` 
只列出依赖项 
``` 
make list-deps 
``` 
但是这只是针对```DEPS```和```BUILD_DEPS```参数的依赖项,上面我们还提到了```TEST_DEPS```、```DOC_DEPS```、```REL_DEPS```和```SHELL_DEPS```,这些怎么办呢?有两个办法: 
1. 用下面命令   
``` 
make fetch-test-deps 
make fetch-doc-deps 
make fetch-rel-deps 
make fetch-shell-deps 
 
make list-test-deps 
make list-doc-deps 
make list-rel-deps 
make list-shell-deps 
```  
2. 或者在```make fetch-deps```或```make list-deps```后面接```DEP_TYPES```参数,参数值可以是test, doc, rel和shell,例如```list-deps DEP_TYPES='test doc'``` 
 
无论用哪个方式,```BUILD_DEPS```和```DEPS```永远都在内 
 
还需要注意的是,上面的办法都只是针对你应用的依赖项,而不会有你依赖项的依赖项 
 
erlang.mk内部,make fetch-*命令把整个依赖项列表保存到下面一些变量名: 
``` 
$(ERLANG_MK_RECURSIVE_DEPS_LIST) 
$(ERLANG_MK_RECURSIVE_TEST_DEPS_LIST) 
$(ERLANG_MK_RECURSIVE_DOC_DEPS_LIST) 
$(ERLANG_MK_RECURSIVE_REL_DEPS_LIST) 
$(ERLANG_MK_RECURSIVE_SHELL_DEPS_LIST) 
``` 
而这些将在make list-*命令的时候被打印出来 
 
##### 忽略不想要的依赖项(Ignoring unwanted dependencies) 
不想要依赖项 
``` 
IGNORE_DEPS += edown proper 
``` 
如果这样写 
``` 
IGNORE_DEPS += edown proper 
TEST_DEPS = proper 
``` 
意味着make和make deps命令将不拉取proper应用,而make test和make check命令还是会拉取proper应用 
 
##### 依赖目录(Dependencies directory) 
依赖项拉取到```$(DEPS_DIR)```目录下,默认名是```deps``` 
你可以修改默认路径,前提是你之前没有定义过它,erlang.mk靠这个变量告诉依赖项到哪里拿到自己的依赖项 
所以你应该用```?=```而不是```=```去修改它(```=```支取最后一次赋值的值,```?=```如果没有赋过值,则等于后面的值) 
不过如果你敢保证没有用到这个项目作为依赖项,直接用```=```也是没问题的,为了避免麻烦,还是这样做吧 
``` 
DEPS_DIR ?= $(CURDIR)/libs 
``` 
##### 多应用程序存储库(Many applications in one repository) 
就是应用本身,还引用了本地另外一个项目作为依赖项,所以叫多应用程序 
这种依赖项和远程依赖项差不多,不同的有以下几点: 
1. 不用拉取 
2. 不会自动封装 
3. ```make distclean```的时候不会删除 
4. 不会自动添加到应用程序资源文件(.app文件) 
 
要正确填好.app文件和编译应用,首先要先定义LOCAL_DEPS变量,它的编译规则和DEPS变量是一样的 
 
如果LOCAL_DEPS被定义了,则决定哪些apps将被构建(包括依赖项),哪些将被添加到.app文件(假如有的话) 
这可以用来指定不同版本构建不同release,如果```LOCAL_DEPS```没有定义,则所有在```$(APPS_DIR)```的apps都将被构建,但是没有app会被加到.app文件 
 
如果出现远程依赖和本地依赖冲突,本地依赖为准,并会引发拉取远程依赖冲突错误 
 
要使用本地依赖库,只要创建名为```$(APPS_DIR)```目录就行了,默认路径是```apps/``` 
 
```make new-app```或者```make new-lib```创建本地依赖库到指定目录,例如: 
``` 
make new-app in=webchat 
make new-lib in=webchat 
``` 
创建模板也可以用本地依赖库 
``` 
make new t=gen_server n=my_server in=webchat 
``` 
##### 自动修补(autopatch) 
erlang.mk会自动修补拉取的所有依赖项,这是为了兼容各个正在使用的erlang.mk版本 
拉取依赖项的时候,会执行以下操作: 
- 按照拉取方法拉取依赖项 
- 如果包含有config.ac或者config.in文件,运行autoreconf -Wall -vif -I m4 
- 如果包含config脚本,运行脚本 
- 在项目中运行autopatch 
autopatch首先检查是否启用了项目指定的修补程序,例如```amqp_client```依赖项的```RABBITMQ_CLIENT_PATCH```,或者```rabbit```依赖项的```RABBITMQ_SERVER_PATCH```,这些只有RabbitMQkpg3.6.0才需要的参数 
好吧,说实话这部分看不懂,感觉有点费解,直接上原文吧 
- Rebar projects are automatically converted to use Erlang.mk as their build tool. This essentially patches Rebar out, and fixes and converts the project to be compatible with Erlang.mk. 
- Erlang.mk projects have their Makefile patched, if necessary, to include the top-level project’s Erlang.mk. This is to ensure that functionality works across all dependencies, even if the dependency’s Erlang.mk is outdated. The patched Makefile can be safely committed if necessary. 
- Other Erlang projects get a small Erlang.mk Makefile generated automatically. 
- Projects with no source directory and no Makefile get an empty Makefile generated, for compatibility purposes. 
- Other projects with no Makefile are left untouched. 
你可以停止erlang.mk的替换通过```NO_AUTOPATH_ERLANG_MK```参数 
``` 
NO_AUTOPATCH_ERLNAG_MK = 1 
``` 
你也可以让一些项目完全停止autopatch 
``` 
NO_AUTOPATCH = cowboy ranch cowlib 
``` 
##### 跳过依赖项(Skipping deps) 
比如不想编译依赖项 
``` 
make SKIP_DEPS=1 
``` 
如果启用这个参数: 
- ```make distclean```命令将不移除```$(DEPS_DIR)```文件 
- 依赖项将不被下载和编译 
 
 |