Rebar:Erlang構建工具

Rebar:Erlang構建工具

http://www.cnblogs.com/panfeng412/archive/2011/08/14/2137990.htmlhtml

Rebar是一款Erlang的構建工具,使用它能夠方便的編譯、測試erlang程序、內聯驅動和打包Erlang發行版本。node

Rebar是一個獨立的erlang腳本,因此使用Rebar發佈程序很是簡單,甚至能夠直接集成在項目文件夾中。默認的狀況下,Rebar會按照Erlang/OTP來組織項目的結構,這樣一來,構建時的配置工做量就會大大減小。Rebar同時提供了依賴庫(包)管理機制,方便程序員重用已存在的模塊。Rebar的依賴管理機制支持的方式很是多,甚至包括Git, Hg等少見的方式。git

下面是一個簡單的例子演示如何將一個已經存在的項目轉化爲使用rebar來構建。程序員

  1. 準備開始
  2. Rebar的命令參數
  3. 構建Rebar
  4. Rebar和OTP約定
  5. 模板支持
  6. 處理髮行版本
  7. 擴展Rebar

1. 準備開始

學習使用Rebar的最好的方法是使用一個簡單的例子來演示如何用Rebar構建Erlang項目。github

1.1 建立項目

首先,咱們爲這個例子項目建立一個文件夾:bootstrap

1 mkdir myapp
2 cd myapp

而後,下載rebar的二進制文件到這個項目的文件夾。注意:若是在你的PATH中間有已經有rebar了,不會對咱們這個例子有影響。bash

複製代碼
1 cd..;
2 git clone git://github.com/basho/rebar.git;
3 cd rebar;
4 ./bootstrap;
5 cd../myapp;
6 mv ../rebar/rebar ./
複製代碼

接下來,咱們使用rebar的模板系統來構建咱們程序的「骨架」。app

1 ./rebar create-app appid=myapp

這條命令執行後會產生一個子文件夾「src」,src包含三個文件夾:框架

  • myapp.app.src:OTP應用程序的資源文件
  • myapp_app.erl:一個OTP應用程序的Application behaviour
  • myapp_sup.erl: 一個OTP應用程序的Supervisor behaviour

1.2 編譯

如今,咱們可使用rebar來編譯這個應用程序:工具

1 ./rebar compile

執行完成後,會產生一個新的文件夾ebin,在其下會生成與src文件夾下源文件對應的beam文件。同時,rebar會根據myapp.app.src動態生成一個合適OTP項目資源文件。

編譯完成後,若是想清除編譯後的beam文件也很是簡單:

1 ./rebar clean

1.3 測試

 

Rebar爲eunit和common_test兩個測試框架都提供了支持,在下面這個例子中,咱們使用eunit來爲咱們的應用程序寫一個測試用例。

打開文件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保護咱們的測試代碼,保證最後的測試代碼不會隨着編譯生成的代碼進入ebin文件夾。

下面咱們來運行這個單元測試用例:

1 ./rebar compile eunit

此時,屏幕上顯示如下相似輸出結果:

複製代碼
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)下,生成的文件會包含調試信息和其餘有用的測試標記。

另外,若是你想檢查咱們單元測試的覆蓋率,能夠經過在myapp/rebar.config添加一行進行配置:

1 {cover_enabled, true}.

而後,從新運行咱們的測試用例,輸入結果以下:

1 ==> myapp (compile)
2 ==> myapp (eunit)
3 Test passed.
4 Cover analysis: /Users/dizzyd/tmp/myapp/.eunit/index.html

有關詳細的代碼覆蓋率分析,被保存在.eunit/index.html文件裏。

2. Rebar的命令參數

Rebar提供了開發中最經常使用的一些操做,包括:

  • 編譯
  • 單元測試和覆蓋分析
  • 靜態分析(經過Dialyzer和Xref)
  • 生成文檔
  • 依賴管理

另外,rebar和reltool提供模板機制以方便OTP嵌入式系統利用。

最常常使用的命令:

命令 描述
compile 編譯項目中全部可用的源文件
eunit 使用Eunit執行單元測試
doc 使用Edoc生成文檔
clean 去掉全部生成的文件。包括編譯,單元測試等過程生成的

較少用的命令(按照字母序):

命令 描述
analyze 使用Dialyzer執行靜態分析
build_plt 構建Dialyzer PLT; 具體描述請看:Dialyzer documentation
check_plt 檢查Dialyzer PLT是不是最新,須要的話從新構建
create 根據模板建立一個典型的項目
create-app 根據模板文件priv/templates/simpleapp.template ,建立一個典型的OTP應用
create-node Create a prototypical OTP embedded system (described by the priv/templates/simplenode.reltool.config template)
delete-deps 刪除rebar.config 設置的依賴庫(包)源文件D
generate 使用 Reltool 構建一個embedded system
get-deps 檢索rebar.config 文件中配置的依賴的代碼
xref 使用Xref 分析依賴

Rebar能夠經過compile指令編譯多種格式的源文件:

源文件 目標文件 描述
src/*.erl ebin/*.beam ERlang的源文件
src/*.app.src ebin/*.app Erlang應用程序的資源文件
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 參數(須要額外安裝protobuffs)

Rebar能夠在rebar.config文件中配置的各類選項:

命令 選項參數 描述
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 目標文件夾
generate overlay_vars Overlay variables file
xref xref_warnings 打開xref的警告
xref xref_checks Xref模塊中analyze/3支持的選項,具體能夠參考: here

3. 構建Rebar

下載rebar:

1 $git clone git://github.com/basho/rebar.git

構建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執行腳本,拷貝這個腳本到項目目錄,開始咱們的rebar之旅。

4. Rebar和OTP約定

Rebar按照OTP的約定組織項目,OTP約定能夠參考:OTP設計原則。基於此,應用程序的目錄須要下列子文件夾:

  • src
  • ebin
  • priv
  • include

應用程序的資源文件(*.app)應該放到ebin文件夾下。

除了上面文件夾,rebar還支持下列的原則:

5. 模板支持

我可使用個人模板嗎?

是的,只要把模板文件(mytemplate.template)放到.rebar/templates下,而後經過下列命令使用:

1 ./rebar create template=mytemplate

6. 管理髮行版本

reltool.config簡介:

erlang經過配置文件reltool.config來幫助建立節點,配置文件中包含rebar和reltool(Erlang R13B引入的發佈管理工具)建立節點須要的信息。

建立應用以下:

1 ./rebar create-app appid=exemplar

注意:create-app和create-node選項可以在rebar_templater.erl中找到,其餘的支持的參數都能在simpleapp.template和simplenode.template中找到。

要建立一個節點,須要先手動建立一個rel目錄:

1 mkdir rel
2 cd rel

而後建立節點:

複製代碼
 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"]}.

最後,執行rebar:

1 $./rebar generate
2 ==> rel (generate)

此時,在rel子目錄中就會生成examplar應用:

複製代碼
$ 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. 擴展Rebar

 

在標準發佈版本中,rebar可以支持大部分erlang開發者的須要。當你碰到須要擴展rebar的需求時,rebar提供一種簡單的方法幫助加入新功能。

(1)Contexts

想要知道如何擴展rebar,一個關鍵的因素就是理解rebar的核心機制——Contexts。Contexts決定在項目目錄結構中選擇那些命令選項執行。

對於哪一個目錄可以執行哪一個選項,contexts沒有限制,經過配置資源文件rebar.app,例如想要在項目的任何一個目錄都執行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的選項與項目中的文件夾和發佈文件夾都關聯。

你能夠經過查看rebar.app瞭解這些,從中學習如何用modules配置參數來使用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).
複製代碼
相關文章
相關標籤/搜索