rebar工具使用備忘錄

http://cryolite.iteye.com/blog/1159448html

rebar是一個開源的erlang應用自動構建工具。 bashotuncer開發。它其實是一個erlang腳本(escript)的工具,所以在不一樣平臺間遷移起來比較方便。 

1.安裝 

能夠去github下載源代碼編譯 
Bash代碼   收藏代碼
  1. git clone git://github.com/basho/rebar.git  


構建rebar工具 
Bash代碼   收藏代碼
  1. cd rebar  
  2. make  


把編譯好的rebar放到系統目錄中完成安裝: 
Bash代碼   收藏代碼
  1. sudo mv rebar /usr/local/bin  


查看rebar的版本檢查一下安裝: 
Bash代碼   收藏代碼
  1. $ rebar -V  

rebar version: 2 date: 20110827_060830 vcs: git 8376693 

不過經過源代碼獲得的是不穩定的版本,使用時會出現些小問題。 
也有現成的穩定rebar下載: 
Bash代碼   收藏代碼
  1. 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)添加一行: 
Bash代碼   收藏代碼
  1. 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的使用訣竅。例如這句 
Rebar.config代碼   收藏代碼
  1. {pre_hooks, [{clean, "./prepare_package_files.sh"},  
  2.      {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: 
Bash代碼   收藏代碼
  1. $ rebar create template=simpleapp  

也能夠建立一個fsm的模塊: 
Bash代碼   收藏代碼
  1. $ rebar create template=simplefsm  

再來一個server模塊: 
Bash代碼   收藏代碼
  1. $ rebar create template=simplesrv  


而後在src查看這些自動生成的代碼就能理解所謂的rebar 自動生成模板是怎麼回事了。 

每類模板都有它們本身的生成控制變量,沒有這些變量,一切都是默認的。例如上面的實驗裏,都沒有指定模塊的控制變量,因此生成的模塊都是叫myxxx之類的缺省名字。 

在rebar源代碼目錄的priv/templates目錄下有全部缺省模板的源程序,查閱這些模板的源碼能夠幫助咱們理解rebar的這些模板建立命令的變量是如何工做的: 
A) simplefsm.template模板 
Simplefsm.template代碼   收藏代碼
  1. {variables, [{fsmid, "myfsm"}]}.  
  2. {template, "simplefsm.erl", "src/{{fsmid}}.erl"}.  


這說明fsm模板提供了一個fsmid的變量控制着fsm模塊的生成,自定義一個: 
Bash代碼   收藏代碼
  1. rebar create template=simplefsm fsmid=cat  


就在src下建立了一個fsm的cat模塊 

B) simplemod.tempalte模板 
Simplemod.tempalte代碼   收藏代碼
  1. {variables, [{modid, "mymod"}]}.  
  2. {template, "simplemod.erl", "src/{{modid}}.erl"}.  
  3. {template, "simplemod_tests.erl", "test/{{modid}}_tests.erl"}.  


能夠經過這個模板建立一個普通的erlang模塊,同時它會自動生成該模塊的單元測試代碼: 
該模板提供的控制變量是modid 

下面建立一個叫fish的erlang模塊: 
Bash代碼   收藏代碼
  1. rebar create template=simplemod modid=fish  


C)basicnif.template模板 
Basicnif.template代碼   收藏代碼
  1. {variables, [{module, "mymodule"}]}.  
  2. {template, "basicnif.erl", "src/{{module}}.erl"}.  
  3. {template, "basicnif.c", "c_src/{{module}}.c"}.  


這個模板是用來生成nif模塊的,它提供了一個叫module的控制變量 
試着生成一個叫dragon的nif模塊看看: 
Bash代碼   收藏代碼
  1. rebar create template=basicnif module=dragon  


nif的c代碼和erl代碼分別放在c_src和src目錄下了。 

D) simpleapp.template模板 
Simpleapp.template代碼   收藏代碼
  1. {variables, [{appid, "myapp"}]}.  
  2. {template, "simpleapp.app.src", "src/{{appid}}.app.src"}.  
  3. {template, "simpleapp_app.erl", "src/{{appid}}_app.erl"}.  
  4. {template, "simpleapp_sup.erl", "src/{{appid}}_sup.erl"}.  


這說明simpleapp模板提供了一個叫appid的變量, 
下面自定義一個叫anmial的應用: 
Bash代碼   收藏代碼
  1. rebar create template=simpleapp appid=anmial  

而後發現src下多了3個和dog application相關的erl源代碼 

實際上,rebar提供了一個直接建立application的子命令create-app: 
Bash代碼   收藏代碼
  1. rebar create-app appid=anmial  

效果同樣。不過命令更短,幫助也詳細(至少告訴咱們模板變量名是 appid) 


下面是以上例子建立了的文件: 
Bash代碼   收藏代碼
  1. 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自動編譯一下: 
Bash代碼   收藏代碼
  1. rebar compile  

能夠發現源代碼分別編譯到ebin和priv兩個目錄下了,erlang是跨平臺的,這沒什麼好說的。神奇的是nif(包括port driver)的動態共享庫(so文件)也自動編譯好了,並且對linux,mac 等自動跨平臺支持。全部這些編譯都由rebar compile一個命令搞定了。 

咱們能夠經過加個-v參數詳細查看編譯過程當中rebar都作了什麼: 
Bash代碼   收藏代碼
  1. rebar compile -v  

控制檯上會詳細打印出編譯過程當中用到的命令和參數,還有相關的環境變量。 

如前所述,這些命令參數咱們能夠經過rebar.config進行指定。例如生成nif動態共享庫的連接參數,若是動態共享庫還須要連接第三方庫,那麼須要爲連接器指定相關連接參數 

比較坑爹的是,若是上面的例子中沒有建立applicaton,compile默認是沒法編譯fsm,server或nif等模塊的。整個工程必須有一個application 
Bash代碼   收藏代碼
  1. 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動態庫的編譯並連接的命令是這樣的: 
Bash代碼   收藏代碼
  1. gcc -std=c99 -fPIC -shared -o gdal_nifs.so gdal_nifs.c -I$ERL_HOME/usr/include -lgdal  

mac下的的編譯連接命令是這樣: 
Bash代碼   收藏代碼
  1. 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定製文件就是 
Rebar.config代碼   收藏代碼
  1. {port_specs, [{"priv/xxxx.so", ["c_src/*.c"}]}.  
  2. {port_env, [  
  3.     {"CFLAGS", "$CFLAGS -std=c99"},  
  4.     {"LDFLAGS", "$LDFLAGS -lgdal"}  
  5.     ]}.  


之後就能夠經過rebar compile跨各類平臺編譯了。 


清理編譯好的文件: 
Bash代碼   收藏代碼
  1. 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數量。 

不過因爲這種並行處理能力,有時候發現會出現靈異現象,好比有次我想同時清理而後編譯: 
Barh代碼   收藏代碼
  1. rebar clean; rebar compile  

發現新的改寫代碼沒有起做用,改爲 
Bash代碼   收藏代碼
  1. rebar clean  
  2. 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中找到這幾行代碼: 
Rebar.config.sample代碼   收藏代碼
  1. %% so_specs - useful for building multiple *.so files  
  2. %%            from one or more object files  
  3. {so_specs, [{"priv/so_name.so", ["c_src/object_file_name.o"]}]}.  
相關文章
相關標籤/搜索