rebar工具使用备忘录
http://cryolite.iteye.com/blog/1159448
1.安装
可以去github下载源代码编译
- git clone git://github.com/basho/rebar.git
构建rebar工具
- cd rebar
- make
把编译好的rebar放到系统目录中完成安装:
- sudo mv rebar /usr/local/bin
查看rebar的版本检查一下安装:
- $ rebar -V
rebar version: 2 date: 20110827_060830 vcs: git 8376693
不过通过源代码得到的是不稳定的版本,使用时会出现些小问题。
也有现成的稳定rebar下载:
- curl -o rebar http://cloud.github.com/downloads/basho/rebar/rebar
2. 使用
2.0 rebar的帮助文档
最基本的文档是README。
有段rebar作者的rebar使用介绍视频, fxxk墙浏览。
rebar的官方文档不是很全,而且rebar的进化也很快,所以最好从rebar本身的帮助开始:通过rebar -h查看rebar帮助。
一个诀窍:在使用rebar时加上-v参数可以详细的打印出rebar构建过程时的相关命令和参数,这有助于我们查看构建工程过程的细节,从而判断rebar.config文件的配置是否正确。-vv会打印稍多信息,而-vvv参数会打印出最罗嗦的调试信息。
2.1 自动补全
rebar版本库中有提供实现自动补全的脚本(在目录priv/shell-completion/bash/下),然后在.bashrc(或者.bash_profile)添加一行:
- source $rebar_home/priv/shell-completion/bash/rebar
以后在命令行窗口中输入rebar命令连按两次tab键会自动列出可用的rebar子命令。当然也可以通过rebar -c 查看每个子命令的详细解释。
在rebar安装目录的priv/templates目录下有所有缺省模板的源代码,查看这些模板的源码有时候能帮助我们理解rebar所做的工作。
当然也可以订阅rebar的邮件列表获得在线帮助
2.3 rebar管理的工程目录结构
rebar管理的erlang工程应该遵循erlang OTP的约定,项目的文件结构如下,子目录src, include下分别放置erlang源代码和hrl包含文件,priv和ebin目录分别放置编译好的lib库共享文件(或可执行文件)和beam文件(和其他文件例如app文件),这两个目录由rebar自动生成并清理,不要把重要的代码放在这两个目录下,虽然不会被rebar clean自动删掉,(不过编译好的beam文件都会删掉),但是也影响不好哈。
此外对port drive和nif的开发,它们的c源程序应该放在c_src目录下。目前port driver和nif是被rebar无区别对待,因此有着同样的rebar控制参数。
总结:源代码应该组织到src, include和c_src三个目录结构中,此外,eunit单元测试代码放在test目录下。rebar控制priv和ebin目录,源码或文档不要在这两个目录下。
实际上,即使没有rebar工程配置文件(rebar.config),只要符合上述目录结构的erlang工程都能自动被rebar编译。
2.4 rebar的工程配置文件
要想更好的使用rebar,一般需要一个rebar工程配置文件(rebar.config)对工程进行管理。
如何写rebar.config配置
rebar安装路径下有一个rebar.config.sample的文件,基本照抄就行了。
此外研究这个文件可以发现许多rebar的使用诀窍。例如这句
- {pre_hooks, [{clean, "./prepare_package_files.sh"},
- {compile, "escript generate_headers"}]}.
这显然是用来控制rebar子命令的前置钩子,也就是说在rebar clean子命令执行之前执行prepare_package_files.sh脚本;在compile子命令执行之前执行escript generate_headers脚本。
当然相应的还有post_hooks后置钩子
2.5 rebar模板的使用
erlang/OTP的3个著名模式都有着各自的程序骨架,每次写一个srv或者fsm的模块,我们都得重复写许多固定的骨架代码,rebar提供了模板帮我们省下了这些重复工作,我们用rebar模版自动生产相应的模版程序估计,然后只管往里面填应用的逻辑的实现代码就行了。
rebar list-templates 子命令可以查看rebar缺省提供的工程模板(当然也可以创建自己的模板)
显然,simplesrv,simplefsm,simpleapp这三个模板是用来创建OTP的服务器模式,有限状态机模式和app应用模式的。
注意在rebar中,这三个模式的约定名称:srv, fsm和app
相应的,这些模板都有一个约定的控制变量,分别是srvid, fsmid和appid
下面做些实验看看
可以试试创建一个application:
- $ rebar create template=simpleapp
也可以创建一个fsm的模块:
- $ rebar create template=simplefsm
再来一个server模块:
- $ rebar create template=simplesrv
然后在src查看这些自动生成的代码就能理解所谓的rebar 自动生成模板是怎么回事了。
每类模板都有它们自己的生成控制变量,没有这些变量,一切都是默认的。例如上面的实验里,都没有指定模块的控制变量,所以生成的模块都是叫myxxx之类的缺省名字。
在rebar源代码目录的priv/templates目录下有所有缺省模板的源程序,查阅这些模板的源码可以帮助我们理解rebar的这些模板创建命令的变量是如何工作的:
A) simplefsm.template模板
- {variables, [{fsmid, "myfsm"}]}.
- {template, "simplefsm.erl", "src/{{fsmid}}.erl"}.
这说明fsm模板提供了一个fsmid的变量控制着fsm模块的生成,自定义一个:
- rebar create template=simplefsm fsmid=cat
就在src下创建了一个fsm的cat模块
B) simplemod.tempalte模板
- {variables, [{modid, "mymod"}]}.
- {template, "simplemod.erl", "src/{{modid}}.erl"}.
- {template, "simplemod_tests.erl", "test/{{modid}}_tests.erl"}.
可以通过这个模板创建一个普通的erlang模块,同时它会自动生成该模块的单元测试代码:
该模板提供的控制变量是modid
下面创建一个叫fish的erlang模块:
- rebar create template=simplemod modid=fish
C)basicnif.template模板
- {variables, [{module, "mymodule"}]}.
- {template, "basicnif.erl", "src/{{module}}.erl"}.
- {template, "basicnif.c", "c_src/{{module}}.c"}.
这个模板是用来生成nif模块的,它提供了一个叫module的控制变量
试着生成一个叫dragon的nif模块看看:
- rebar create template=basicnif module=dragon
nif的c代码和erl代码分别放在c_src和src目录下了。
D) simpleapp.template模板
- {variables, [{appid, "myapp"}]}.
- {template, "simpleapp.app.src", "src/{{appid}}.app.src"}.
- {template, "simpleapp_app.erl", "src/{{appid}}_app.erl"}.
- {template, "simpleapp_sup.erl", "src/{{appid}}_sup.erl"}.
这说明simpleapp模板提供了一个叫appid的变量,
下面自定义一个叫anmial的应用:
- rebar create template=simpleapp appid=anmial
然后发现src下多了3个和dog application相关的erl源代码
实际上,rebar提供了一个直接创建application的子命令create-app:
- rebar create-app appid=anmial
效果一样。不过命令更短,帮助也详细(至少告诉我们模板变量名是 appid)
下面是以上例子创建了的文件:
- find .
.
./c_src
./c_src/dragon.c
./src
./src/anmial_app.erl
./src/cat.erl
./src/anmial_sup.erl
./src/anmial.app.src
./src/fish.erl
./src/myfsm.erl
./src/dragon.erl
./test
./test/fish_tests.erl
用rebar自动编译一下:
- rebar compile
可以发现源代码分别编译到ebin和priv两个目录下了,erlang是跨平台的,这没什么好说的。神奇的是nif(包括port driver)的动态共享库(so文件)也自动编译好了,而且对linux,mac 等自动跨平台支持。所有这些编译都由rebar compile一个命令搞定了。
我们可以通过加个-v参数详细查看编译过程中rebar都做了什么:
- rebar compile -v
控制台上会详细打印出编译过程中用到的命令和参数,还有相关的环境变量。
如前所述,这些命令参数我们可以通过rebar.config进行指定。例如生成nif动态共享库的链接参数,如果动态共享库还需要链接第三方库,那么需要为链接器指定相关链接参数
比较坑爹的是,如果上面的例子中没有创建applicaton,compile默认是无法编译fsm,server或nif等模块的。整个工程必须有一个application
- rebar create-app appid=animal
对于nif模块也是如此。
可以在rebar.config中通过为port_envs设置环境变量CFLAGS和LDFLAGS指定编译或链接的参数:
在port_envs哪些变量可以定制,似乎没有什么在线文档,所以直接看rebar的源代码程序:rebar_port_compiler.erl。开头的注释中就说明了可以定制哪些参数,有编译的也有链接的。
举个例子,我最近写的一个nif模块c代码用到了c99的一些特性,还使用到了一个第三方共享库gdal。linux下nif动态库的编译并链接的命令是这样的:
- gcc -std=c99 -fPIC -shared -o gdal_nifs.so gdal_nifs.c -I$ERL_HOME/usr/include -lgdal
mac下的的编译链接命令是这样:
- gcc -std=c99 -fPIC -bundle -undefined suppress -flat_namespace -o gdal_nifs.so gdal_nifs.c -I$ERL_HOME/usr/include -lgdal
rebar已经考虑了跨平台编译链接的不同参数问题,我还需要定制以下两个参数:
1) 指定 c99 标准编译; -std=c99
2) 指定gdal动态库的链接: -lgdal
因此,我的rebar.config定制文件就是
- {port_specs, [{"priv/xxxx.so", ["c_src/*.c"}]}.
- {port_env, [
- {"CFLAGS", "$CFLAGS -std=c99"},
- {"LDFLAGS", "$LDFLAGS -lgdal"}
- ]}.
以后就可以通过rebar compile跨各种平台编译了。
清理编译好的文件:
- rebar clean
刚才rebar自动编译好的目标文件(beam和so)都会自动删掉。
注:该命令不会清除所有目标文件,它只清除由rebar生成的文件。
模板是针对某种有着固定模式或结构的代码的,实际上我们也可以自己写模版。自己的代码模板可以放在工程的priv/templates目录下。rebar list-templates会自动列出该目录和当前目录下的所有模板,模板格式看一下官方提供的例子,简单的说就是模板变量的字符串替换,也没啥高深的。
要是觉得自己的模板不错也可以提交上去有可能会成为官方模板哦。
3.依赖的管理
较大的应用会依赖其它应用,rebar提供了对这些依赖的管理。在erlang工程的目录结构上,rebar对此有所扩展,所有的其他依赖应用都放在deps目录下,这是rebar工程比较独特的地方。
工程依赖的其他应用都会放在deps目录下。在rebar.config配置,一个例子:
{deps, [
{lager, ".*", {git, "git://github.com/basho/lager", {branch, "master"}}},
{poolboy, ".*", {git, "git://github.com/basho/poolboy", {branch, "master"}}},
{webmachine, ".*", {git, "git://github.com/basho/webmachine",
{branch, "master"}}}
]}.
项目的目录结构:
tree -L 2
.
├── deps
│ ├── lager
│ ├── poolboy
│ ├── mochiweb
│ └── webmachine
├── ebin
├── priv
├── rebar.config
└── src
├── xxx_app.erl
├── xxx.app.src
└── xxx_sup.erl
(其中mochiweb又是webmachine依赖的应用)
一个问题是依赖的应用还依赖其它应用,这时要注意deps配置参数中这些应用的顺序,例如如果上述配置中(举个例子)可能许多其它应用都依赖lager这个应用,这时,lager的配置就应该放在它们之前。
5.常见问题
1)
rebar有着erlang的并行处理能力,缺省情况下每个子命令有3个job worker并行处理,可以通过-j参数控制并行处理的worker数量。
不过由于这种并行处理能力,有时候发现会出现灵异现象,比如有次我想同时清理然后编译:
- rebar clean; rebar compile
发现新的改写代码没有起作用,改成
- rebar clean
- rebar compile
就没有问题了。
现在我的用法是:
rebar clean compile
2。如果有以下情况:
- 某个应用没有启动;
- lib下没有某个应用;
- lib下某个应用对应的目录没有版本信息;
- lib下某个应用对应的目录没有编译好的beam文件
这是因为对应的应用没有编译,就直接rebar generate的原故。
依赖的第三方应用,包括本应用没有编译过,(即每个应用ebin目录下没有beam文件),则rebar generate生成的发布目录中的时候就不会有对应的应用(可以看到该应用其实是一个空壳:对应的目录不带版本信息,而且没有beam文件),即使在reltool.config中指定了这些应用也没用。
3. 如果希望系统启动时,某个应用随之启动
第三方应用可能并不保证在系统初始化时启动,要想让其在初始化时启动,可以在reltool.config文件的修改'rel'项,增加对应的应用,例如想让lager初始化时自动启动:
{rel, "xxx", "1.0", [kernel, stdlib,sasl, lager, xxx]}
因为rebar文档不全,而且几乎每天都有代码修改,处于不断的快速进化中,早期的文档现在看来有的陈旧了,比如网上许多文档都提到了rebar的dialyzer静态分析,实际上最新的rebar已经不再有这个子命令了。
遇到问题一般可以去翻翻rebar.config.sample,这个配置模板提供了rebar.config的几乎所有配置变量及其说明。比如我的需求中需要写好几个nif模块,每个nif模块都有自己对应的so.在rebar.config.sample中找到这几行代码:
- %% so_specs - useful for building multiple *.so files
- %% from one or more object files
- {so_specs, [{"priv/so_name.so", ["c_src/object_file_name.o"]}]}.
rebar工具使用备忘录的更多相关文章
- Spring常用工具方法备忘录
1:加载配置文件 Resource resource = new ClassPathResource("log4j.properties"); Properties default ...
- 转载:rebar和erlang
使用rebar生成erlang release 并进行热代码升级 http://blog.sina.com.cn/s/blog_6530ad590100wmkn.html 使用rebar工具开发erl ...
- rebar安装及创建项目
rebar作为erlang开发中编译,构建,发布,打包,动态升级的常用工具,下面我记录下rebar工具的安装及使用 从源码安装rebar 1. 建立文件 install_rebar.sh 2. 拷贝如 ...
- erlang 一个高性能web框架 Cowboy 的使用笔记
环境:ubuntu_server 1210 目的:构建web版hello world程序 参考链接:http://roberto-aloi.com/blog/2013/07/13/create-dep ...
- Rebar:Erlang构建工具
Rebar是一款Erlang的构建工具,使用它可以方便的编译.测试erlang程序.内联驱动和打包Erlang发行版本. Rebar是一个独立的erlang脚本,所以使用Rebar发布程序非常简单,甚 ...
- Erlang:[笔记三,构建工具rebar之使用依赖]
概述 类似Java中的Maven,Gradle,在Erlang中同样也有包管理的工具,Rebar提供Erlang依赖(包)管理机制,开发人员可以重复使用已有的模块,通过rebar引入自己的项目直接使用 ...
- Erlang:[笔记一,构建工具rebar之编译]
Rebar概述 Rebar是一款Erlang构建工具,使用它可以方便的编译,测试erlang程序和打包erlang发行版本.Rebar其实是一个独立的erlang脚本,默认情况下,Rebar会按照Er ...
- android开发环境与工具使用相关备忘录
一.名称简介 1.ADT(Android Development Tools) 可以简单理解为在eclipse下开发安卓的插件或工具包. 查看当前ADT版本方法:help-> about ecl ...
- 备忘录之 —— .bashrc(IC工具篇)
好久没有使用这些IC工具了,装在自己的虚拟机中的Linux系统里面,现在想要卸载掉,想起之前自己辛辛苦苦的折腾这些工具配置,如果直接删除,感觉未免有点对不起自己的劳动成果,或许以后再也用不到了,就当是 ...
随机推荐
- RPC调用框架比较分析--转载
原文地址:http://itindex.net/detail/52530-rpc-%E6%A1%86%E6%9E%B6-%E5%88%86%E6%9E%90 什么是RPC: RPC(Remote Pr ...
- menuconfig_kconfig
这一节的主要内容: Menuconfig的操作 Kconfig和.config文件 Linux内核配置裁剪实验 linux编译器通过.config文件确认哪些代码编译进内核,哪些被裁减掉 menuco ...
- Python中的Sets数据结构
Python的set和其他语言类似,是一个无序不重复元素集,基本功能包括关系测试和消除重复元素.集合对象支持union(联合),intersection(交),difference(差)和sysmme ...
- 20160206.CCPP体系具体解释(0016天)
代码片段(01):.指针.c+02.间接赋值.c 内容概要:内存 ///01.指针 #include <stdio.h> #include <stdlib.h> //01.取地 ...
- 适用android的MVP:怎样组织展示层
原文 MVP for Android:How to organize presentation layer http://antonioleiva.com/mvp-android/ 译文 MVP(Mo ...
- Android 用SQLite 使用 CursorLoader 中的数据填充列表视图
我做了简单的测试应用程序基于此示例.有一个按钮,插入到数据库和列表视图的数据.都是在 MainActivity 中.在原来的代码是restartLoader() 仅从调用 onResume() ,但它 ...
- C语言深度剖析-----最终的胜利
进军C++ 初始OOP 抽象 封装 封装的好处,改名只需改封装 小结 面试题 指针运算 打印11,16,29,28,26 调试经验 printf定义,可变参数无法判断实际参数的类型 安全编程 数组 ...
- php ignore_user_abort()实现计划(定时执行)任务功能
? 1 2 3 4 5 6 7 8 9 10 11 12 <?php ignore_user_abort(TRUE); //关掉浏览器,PHP脚本也可以继续执行. set_ti ...
- [WPF自定义控件库]排序、筛选以及高亮
1. 如何让列表的内容更容易查找 假设有这么一个列表(数据源在本地),由于内容太多,要查找到其中某个想要的数据会比较困难.要优化这个列表,无非就是排序.筛选和高亮. 改造过的结果如上. 2. 排序 在 ...
- MCI
MCI(Media Control Interface)媒体控件接口是Mircrosoft提供的一组多媒体和文件的标准接口.它的好处是可以方便地控制绝大多数多媒体设备 包括音频,视频,影碟,录像等多媒 ...