安装
1git clone git://github.com/basho/rebar.git
2cd rebar
3make
4sudo cp rebar /usr/local/bin
或使用稳定的版本:
1curl -o rebar http://cloud.github.com/downloads/basho/rebar/rebar
使用
rebar作者教程:http://vimeo.com/8311407
rebar官方文档:https://github.com/basho/rebar/wiki
rebar的工程配置文件
每个erlang工程会有一个rebar.config控制rebar的使用,当然rebar.config不是必须的,没有的话一切都按rebar缺省的来。rebar安装路径下有一个rebar.config.sample的文件,研究这个文件可以发现许多rebar的使用诀窍。
使用rebar时加上-v参数可以详细的打印出rebar构建过程时的相关命令和参数,这有助于我们查看rebar.config文件的配置是否正确。
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 list-templates 子命令可以查看rebar缺省提供的工程模板(当然也可以创建自己的模板)
模板是针对某种有着固定模式或结构的代码的,例如OTP的3个著名模式都有着各自的程序骨架,每次写一个srv或者fsm的模块,我们都得重复写许多固定的骨架代码,rebar通过模板帮我们省下了这些重复工作,我们只管往里面填应用的逻辑代码就行了。
显然,simplesrv,simplefsm,simpleapp这三个模板是用来创建OTP的服务器模式,有限状态机模式和app应用模式的。
注意在rebar中,这三个模式的约定名称:srv, fsm和app 。相应的,这些模板都有一个约定的控制变量,分别是srvid, fsmid和appid
1rebar create template=simpleapp
2rebar create-app appid=anmial
3
4rebar create template=simplefsm
5
6rebar create template=simplesrv
7
8rebar compile
9rebar compile -v
10
rebar.config
erl_opts
概述
使用rebar构建Erlang project的时候,通过设置rebar.config可以为rebar配置各种选项。
其中比较常用的有 erl_opts 这个选项。
1{erl_opts, [smp, debug_info, {d, 'APP', myproject}, {d, debug}]}.
实际上它是设置Erlang Compiler的参数。(详细说明见 http://www.erlang.org/doc/man/compile.html)
平时我们可以在每个 .erl 文件的头部写上这种语句
1-compile({no_auto_import,[error/1]}).
来告诉编译器编译本文件时用到的编译选项。
如果把这些参数放在rebar.config里面设置的话,就可以对所有文件使用同一套编译参数了。
比如在rebar.config里面:
1{erl_opts, [smp, debug_info, nowarn_unused_function]}.
这里设置了nowarn_unused_function,即module中有未被使用的function时不触发警告。
效果等同于在每个module文件中加入这句
1-compile(nowarn_unused_function).
{d, macro, value}
有如下情景,使用rebar.config来配置全局编译参数时会比较方便:
在开发和调试阶段,可能有需要在console打印一些调试信息,通常会用到io:format. 但是发布的程序,在正式环境下是不需要打印这些东西的。
那么我们可以这样做。
在rebar.config设置erl_opts, 定义一个Macro, {d, debug}, 表示调试模式。
1{erl_opts, [smp, no_debug_info, {d, debug}]}.
然后在一个全局的hrl文件中定义输出调试信息的Macro
1-ifdef(debug).
2-define(TRACE(Str), io:format(Str)).
3-define(TRACE(Str, Args), io:format(Str, Args)).
4-else.
5-define(TRACE(Str), void).
6-define(TRACE(Str, Args), void).
7-endif.
这样,我们在需要打印调试信息的地方用
TRACE(“something to show”) 而不是直接用 io:format.
好处是, 当发布正式版本时, 只须要把rebar.config里面的{d, debug}去掉而不用改动代码,就可以不打印调试信息了。
{i,Dir}
{i,Dir}-在包含文件时将Dir添加到要搜索的目录列表中。当遇到-include或-include_lib指令时,编译器会在以下目录中搜索头文件:
- “.”,文件服务器的当前工作目录
- 编译文件的基本名称
- 使用选项i指定的目录;首先搜索最后指定的目录
deps
这里面放的是依赖库,然后应用程序就可以直接调用对应模块的函数了。
port_envs
可以在rebar.config中通过为port_envs设置环境变量CFLAGS和LDFLAGS指定编译或链接的参数。
在port_envs哪些变量可以定制,似乎没有什么在线文档,所以直接看rebar的源代码程序:rebar_port_compiler.erl。开头的注释中就说明了可以定制哪些参数,有编译的也有链接的。
举个例子,我最近写的一个nif模块c代码用到了c99的一些特性,还使用到了一个第三方共享库gdal。linux下nif动态库的编译并链接的命令是这样的:
1gcc -std=c99 -fPIC -shared -o gdal_nifs.so gdal_nifs.c -I$ERL_HOME/usr/include -lgdal
mac下的的编译链接命令是这样:
1gcc -std=c99 -fPIC -bundle -undefined suppress -flat_namespace -o gdal_nifs.so gdal_nifs.c -I$ERL_HOME/usr/include -lgdal
rebar已经考虑了跨平台编译链接的不同参数问题,我还需要定制以下两个参数:
- 指定 c99 标准编译; -std=c99
- 指定gdal动态库的链接: -lgdal
因此,我的rebar.config定制文件就是
1{port_envs, [
2 {"CFLAGS", "$CFLAGS -std=c99"},
3 {"LDFLAGS", "$LDFLAGS -lgdal"}
4 ]}.
以后就可以通过rebar compile跨各种平台编译了。
port_specs
要编译的文件名或通配符列表。也可能包含元组,由应用于系统的正则表达式组成,架构作为过滤器
rebar.config.sample
https://github.com/rebar/rebar/blame/b6d309417c502ca243f810e5313bea36951ef038/rebar.config.sample