Rebar:Erlang構(gòu)建工具
Rebar是一款Erlang的構(gòu)建工具,使用它可以方便的編譯、測試erlang程序、內(nèi)聯(lián)驅(qū)動和打包Erlang發(fā)行版本。
Rebar是一個獨立的erlang腳本,所以使用Rebar發(fā)布程序非常簡單,甚至可以直接集成在項目文件夾中。默認(rèn)的情況下,Rebar會按照Erlang/OTP來組織項目的結(jié)構(gòu),這樣一來,構(gòu)建時的配置工作量就會大大減少。Rebar同時提供了依賴庫(包)管理機(jī)制,方便程序員重用已存在的模塊。Rebar的依賴管理機(jī)制支持的方式非常多,甚至包括Git, Hg等少見的方式。
下面是一個簡單的例子演示如何將一個已經(jīng)存在的項目轉(zhuǎn)化為使用rebar來構(gòu)建。
- 準(zhǔn)備開始
- Rebar的命令參數(shù)
- 構(gòu)建Rebar
- Rebar和OTP約定
- 模板支持
- 處理發(fā)行版本
- 擴(kuò)展Rebar
1. 準(zhǔn)備開始
學(xué)習(xí)使用Rebar的最好的方法是使用一個簡單的例子來演示如何用Rebar構(gòu)建Erlang項目。
1.1 創(chuàng)建項目
首先,我們?yōu)檫@個例子項目創(chuàng)建一個文件夾:
1 mkdir myapp
2 cd myapp
然后,下載rebar的二進(jìn)制文件到這個項目的文件夾。注意:如果在你的PATH中間有已經(jīng)有rebar了,不會對我們這個例子有影響。
1 cd..;
2 git clone git://github.com/basho/rebar.git;
3 cd rebar;
4 ./bootstrap;
5 cd../myapp;
6 mv ../rebar/rebar ./
接下來,我們使用rebar的模板系統(tǒng)來構(gòu)建我們程序的“骨架”。
1 ./rebar create-app appid=myapp
這條命令執(zhí)行后會產(chǎn)生一個子文件夾“src”,src包含三個文件夾:
- myapp.app.src:OTP應(yīng)用程序的資源文件
- myapp_app.erl:一個OTP應(yīng)用程序的Application behaviour
- myapp_sup.erl: 一個OTP應(yīng)用程序的Supervisor behaviour
1.2 編譯
現(xiàn)在,我們可以使用rebar來編譯這個應(yīng)用程序:
1 ./rebar compile
執(zhí)行完成后,會產(chǎn)生一個新的文件夾ebin,在其下會生成與src文件夾下源文件對應(yīng)的beam文件。同時,rebar會根據(jù)myapp.app.src動態(tài)生成一個合適OTP項目資源文件。
編譯完成后,如果想清除編譯后的beam文件也非常簡單:
1 ./rebar clean
1.3 測試
Rebar為eunit和common_test兩個測試框架都提供了支持,在下面這個例子中,我們使用eunit來為我們的應(yīng)用程序?qū)懸粋€測試用例。
打開文件src/myapp_app.erl,在-export()指令之后添加如下代碼:
1 -ifdef(TEST).
2 -include_lib(“eunit/include/eunit.hrl”).
3 -endif.
然后在這個文件的最后添加:
1 -ifdef(TEST).
2 simple_test() ->
3 ok = application:start(myapp),
4 ?assertNot(undefined == whereis(myapp_sup)).
5 -endif.
通過使用ifdef保護(hù)我們的測試代碼,保證最后的測試代碼不會隨著編譯生成的代碼進(jìn)入ebin文件夾。
下面我們來運(yùn)行這個單元測試用例:
1 ./rebar compile eunit
此時,屏幕上顯示以下類似輸出結(jié)果:
1 ==> myapp (compile)
2 Compiled src/myapp_app.erl
3 Compiled src/myapp_sup.erl
4 ==> myapp (eunit)
5 Compiled src/myapp_sup.erl
6 Compiled src/myapp_app.erl
7 Test passed.
注意:本次操作中rebar會編譯myapp_app.erl文件兩遍,第二遍編譯會將輸出放到一個特殊的文件夾(.eunit)下,生成的文件會包含調(diào)試信息和其他有用的測試標(biāo)記。
另外,如果你想檢查我們單元測試的覆蓋率,可以通過在myapp/rebar.config添加一行進(jìn)行配置:
1 {cover_enabled, true}.
然后,重新運(yùn)行我們的測試用例,輸入結(jié)果如下:
1 ==> myapp (compile)
2 ==> myapp (eunit)
3 Test passed.
4 Cover analysis: /Users/dizzyd/tmp/myapp/.eunit/index.html
有關(guān)詳細(xì)的代碼覆蓋率分析,被保存在.eunit/index.html文件里。
2. Rebar的命令參數(shù)
Rebar提供了開發(fā)中最常用的一些操作,包括:
- 編譯
- 單元測試和覆蓋分析
- 靜態(tài)分析(通過Dialyzer和Xref)
- 生成文檔
- 依賴管理
另外,rebar和reltool提供模板機(jī)制以方便OTP嵌入式系統(tǒng)利用。
最經(jīng)常使用的命令:
| 命令 | 描述 |
| compile | 編譯項目中所有可用的源文件 |
| eunit | 使用Eunit執(zhí)行單元測試 |
| doc | 使用Edoc生成文檔 |
| clean | 去掉所有生成的文件。包括編譯,單元測試等過程生成的 |
較少用的命令(按照字母序):
| 命令 | 描述 |
| analyze | 使用Dialyzer執(zhí)行靜態(tài)分析 |
| build_plt | 構(gòu)建Dialyzer PLT; 具體描述請看:Dialyzer documentation |
| check_plt | 檢查Dialyzer PLT是否是最新,需要的話重新構(gòu)建 |
| create | 根據(jù)模板創(chuàng)建一個典型的項目 |
| create-app | 根據(jù)模板文件priv/templates/simpleapp.template ,創(chuàng)建一個典型的OTP應(yīng)用 |
| create-node | Create a prototypical OTP embedded system (described by the priv/templates/simplenode.reltool.config template) |
| delete-deps | 刪除rebar.config 設(shè)置的依賴庫(包)源文件D |
| generate | 使用 Reltool 構(gòu)建一個embedded system |
| get-deps | 檢索rebar.config 文件中配置的依賴的代碼 |
| xref | 使用Xref 分析依賴 |
Rebar可以通過compile指令編譯多種格式的源文件:
| 源文件 | 目標(biāo)文件 | 描述 |
| src/*.erl | ebin/*.beam | ERlang的源文件 |
| src/*.app.src | ebin/*.app | Erlang應(yīng)用程序的資源文件 |
| c_src/*.c | priv/<app>.so | port driver的c語言源代碼或者NIF共享鏈接庫 |
| mibs/*.mib | priv/mibs/*.bin | SNMP 的mib 文件 |
| src/*.xrl | src/*.erl | Leex 生成的文件 |
| src/*.yrl | src/*.erl | Yecc 生成的文件 |
| asn1/*.asn1 | src/*.erl | ASN-1文件 |
| templates/*.dtl | ebin/*_dtl.beam | ErlyDTL模板文件 (需要額外安裝 ErlyDTL) |
| src/*.lfe | ebin/*.beam | LFE 源文件 (需要額外安裝LFE) |
| src/*.peg | ebin/*.beam | Neotoma PEG 語法源文件 (需要額外安裝Neotoma) |
| src/*.proto | ebin/*_pb.beam, include/*_pb.hrl | Protocol Buffers 參數(shù)(需要額外安裝protobuffs) |
Rebar可以在rebar.config文件中配置的各種選項:
| 命令 | 選項參數(shù) | 描述 |
| compile | erl_first_files | 需要提前編譯的erlang源文件(例如behavior模塊) |
| compile | erl_opts | 編譯器支持的其他選項,詳情請見 here |
| compile | mib_first_files | 需要提前編譯的mib文件列表 (例如, mib 文件中import部分的引用的RFC文件 |
| compile | src_dirs | 列出其他包含erlang源文件的目錄 |
| compile | erlydtl_opts | 更多的支持的選項查閱 ErlyDTL Templates |
| clean | clean_files | 需要在clean步驟刪除的文件列表,列出那些需要clean指令刪除的其他模塊的文件 |
| doc | edoc_opts | edoc 支持的指令,詳見:here |
| eunit | eunit_opts | Eunit支持的指令,詳見 here |
| eunit | cover_enabled | 開啟erlang的覆蓋率分析 |
| eunit | eunit_compile_opts | Eunit編譯時用到的其他的選項 |
| analyze | dialyzer_opts | 指定Dialyzer PLT 文件 |
| build_plt | dialyzer_opts | 指定Dialyzer PLT 文件 |
| check_plt | dialyzer_opts | 指定 Dialyzer PLT 文件 |
| get-deps, delete-deps | base_dir | 為deps_dir 指定一個候選的目錄 |
| get-deps, delete-deps | deps_dir | 制定一個文件夾存儲依賴 |
| get-deps, delete-deps | deps | 依賴的列表 |
| generate | target_dir | 目標(biāo)文件夾 |
| generate | overlay_vars | Overlay variables file |
| xref | xref_warnings | 打開xref的警告 |
| xref | xref_checks | Xref模塊中analyze/3支持的選項,具體可以參考: here |
3. 構(gòu)建Rebar
下載rebar:
1 $git clone git://github.com/basho/rebar.git
構(gòu)建rebar:
1 $cd rebar
2 $./bootstrap
3 Recompile: src/rebar_core
4 ==> rebar (compile)
5 Congratulations! You now have a self-contained script called “rebar” in your current working directory. Place this script anywhere in your path and you can use rebar to build OTP-compliant apps.
此時,我們有了一個rebar執(zhí)行腳本,拷貝這個腳本到項目目錄,開始我們的rebar之旅。
4. Rebar和OTP約定
Rebar按照OTP的約定組織項目,OTP約定可以參考:OTP設(shè)計原則。基于此,應(yīng)用程序的目錄需要下列子文件夾:
- src
- ebin
- priv
- include
應(yīng)用程序的資源文件(*.app)應(yīng)該放到ebin文件夾下。
除了上面文件夾,rebar還支持下列的原則:
- test:包含EUnit測試腳本的文件夾
- c_src:包含c語言寫的port drivers
5. 模板支持
我可以使用我的模板嗎?
是的,只要把模板文件(mytemplate.template)放到.rebar/templates下,然后通過下列命令使用:
1 ./rebar create template=mytemplate
6. 管理發(fā)行版本
reltool.config簡介:
erlang通過配置文件reltool.config來幫助創(chuàng)建節(jié)點,配置文件中包含rebar和reltool(Erlang R13B引入的發(fā)布管理工具)創(chuàng)建節(jié)點需要的信息。
創(chuàng)建應(yīng)用如下:
1 ./rebar create-app appid=exemplar
注意:create-app和create-node選項能夠在rebar_templater.erl中找到,其他的支持的參數(shù)都能在simpleapp.template和simplenode.template中找到。
要創(chuàng)建一個節(jié)點,需要先手動創(chuàng)建一個rel目錄:
1 mkdir rel
2 cd rel
然后創(chuàng)建節(jié)點:
1 $../rebar create-node nodeid=exemplar
2 $ ls -lR
3 .:
4 total 8
5 drwxr-xr-x 2 jiuling.ypf users 4096 Apr 1111:08files
6 -rw-r–r– 1 jiuling.ypf users 806 Apr 1111:08 reltool.config
7 ./files:
8 total 28
9 -rw-r–r– 1 jiuling.ypf 334 Apr 1111:08 app.config
10 -rwxr–r– 1 jiuling.ypf users 1120 Apr 1111:08 erl
11 -rwxr–r– 1 jiuling.ypf users 4370 Apr 1111:08 exemplar
12 -rwxr–r– 1 jiuling.ypf users 4819 Apr 1111:08 nodetool
13 -rw-r–r– 1 jiuling.ypf users 423 Apr 1111:08 vm.args
同時,還需要在rebar.config中添加一行sub_dirs:
1 {sub_dirs, ["rel"]}.
最后,執(zhí)行rebar:
1 $./rebar generate
2 ==> rel (generate)
此時,在rel子目錄中就會生成examplar應(yīng)用:
$ ls -l rel/exemplar/
total 24
drwxr-xr-x 2 jiuling.ypf users 4096 Apr 1111:09 bin
drwxr-xr-x 8 jiuling.ypf users 4096 Apr 1111:09 erts-5.8
drwxr-xr-x 2 jiuling.ypf users 4096 Apr 1111:09 etc
drwxr-xr-x 18 jiuling.ypf users 4096 Apr 1111:09 lib
drwxr-xr-x 3 jiuling.ypf users 4096 Apr 1111:09 log
drwxr-xr-x 3 jiuling.ypf users 4096 Apr 1111:09 releases
7. 擴(kuò)展Rebar
在標(biāo)準(zhǔn)發(fā)布版本中,rebar能夠支持大部分erlang開發(fā)者的需要。當(dāng)你碰到需要擴(kuò)展rebar的需求時,rebar提供一種簡單的方法幫助加入新功能。
(1)Contexts
想要知道如何擴(kuò)展rebar,一個關(guān)鍵的因素就是理解rebar的核心機(jī)制——Contexts。Contexts決定在項目目錄結(jié)構(gòu)中選擇那些命令選項執(zhí)行。
對于哪個目錄能夠執(zhí)行哪個選項,contexts沒有限制,通過配置資源文件rebar.app,例如想要在項目的任何一個目錄都執(zhí)行any_dir_modules,需要在rebar.app中添加:
1 {application, rebar,
2 [{description,"Rebar: Erlang Build Tool"},
3 %% ...
4 {env, [
5 %% ...
6 %% any_dir processing modules
7 {any_dir_modules, [
8 %% ...
9 rebar_exemplar
10 ]},
11 %% …
12 ]}
13 ]}.
(2)Module context
Module context允許rebar的選項與項目中的文件夾和發(fā)布文件夾都關(guān)聯(lián)。
你可以通過查看rebar.app了解這些,從中學(xué)習(xí)如何用modules配置參數(shù)來使用app_dir和rel_dir。
例子,EDoc command<strong>修改</strong>rebar.app:
1 {application, rebar,
2 [{description,"Rebar: Erlang Build Tool"},
3 {vsn,"2"},
4 {modules, [ rebar,
5 %% ...
6 rebar_edoc,
7 %% ...
8 mustache ]},
9 {registered, []},
10 {applications, [kernel,
11 stdlib,
12 sasl]},
13 {env, [
14 %% ...
15 %% Dir specific processing modules
16 {modules, [
17 {app_dir, [
18 %% ...
19 rebar_edoc,
20 %% ...
21 ]},
22 {rel_dir, [
23 rebar_reltool
24 ]}
25 ]}
26 ]}
27 ]}.
(3)引入rebar_edoc模塊
1 -module(rebar_edoc).
2 -export([doc/2, clean/2]).
3 -include(“rebar.hrl”).
4
5 %% @doc Generate Erlang program documentation.
6 %% @spec doc(#config{}, string()) -> ok
7 -spec(doc(Config::#config{}, File::string()) -> ok).
8 doc(Config, File) ->
9 {ok, AppName, _AppData} = rebar_app_utils:load_app_file(File),
10 EDocOpts = rebar_config:get(Config, edoc_opts, []),
11 ok = edoc:application(AppName, “.”, EDocOpts),
12 ok.
13
14 %% @doc Remove the generated Erlang program documentation.
15 %% @spec clean(#config{}, string()) -> ok
16 -spec(clean(Config::#config{}, File::string()) -> ok).
17 clean(Config, _File) ->
18 EDocOpts = rebar_config:get(Config, edoc_opts, []),
19 DocDir = proplists:get_value(dir, EDocOpts, “doc”),
20 rebar_file_utils:rm_rf(DocDir).
浙公網(wǎng)安備 33010602011771號