OTP application 最後發布時,需要一個工具幫我們分析 application 的相關 dependency libraries,發布正確的 OTP application。
目前有看到三個 release 工具: reltool, rebar, relx,雖然 reltool 是 OTP 官方提供的封裝工具,前面的部份先簡述 reltool 與 relx,relx 是因為 survey 了 cowboy 的關係,而去了解,功能跟 rebar 類似,但提供了更高階的封裝簡化工具,這個工具是 erlware 這個組織開發提供的。rebar 提供了比 reltool 高階的封裝方式,我們就以 rebar 為主,因為 rebar 的文件說明比 relx 還清楚。
reltool
reltool提供 GUI 與 CLI 兩種界面
reltool user guide
reltool doc
reltool使用指南
reltool使用入門
erlang.mk and relx
建構 OTP releases 一直以來都是個很麻煩的工作,除了 reltool, rebar 之外 cowboy 作者提供了另一個建立 application 的方式。
建立 OTP release 需要兩個步驟:
- compile source
erlang.mk 用來處理第一個步驟,erlang.mk 是 GNU Makefile 的一個 include file,它可以用來 build project, 取得 building dependencies,產生文件,做 dialyzer 靜態分析。 - create a release
relx 是個 release creation tool,它是一個執行檔。用來封裝OTP application,裡面包含了Erlang runtime, a boot script to start the node and all its applications, configuration files
最簡單的 Makefile,就只需要一個 PORJECT name 並 include erlang.mk
PROJECT = my_project
include erlang.mk
DEPS 定義本專案相關的 dependencies,條列出來後,在下面以 dep_cowboy 的方式定義該 library 的 repository URL 以及 commit number, tag 或 branch。 .PHONY 表示有兩個 build target,預設是 release。 release 最後會使用 relx 將 project 建構在 rel 目錄中。
PROJECT = ninenines
DEPS = cowboy erlydtl
dep_cowboy = https://github.com/extend/cowboy.git 0.8.5
dep_erlydtl = https://github.com/evanmiller/erlydtl.git 4d0dc8fb
.PHONY: release clean-release
release: clean-release all projects
relx -o rel/$(PROJECT)
clean-release: clean-projects
rm -rf rel/$(PROJECT)
include erlang.mk
這是 relx.config 檔,第一行定義 release name: ninenines,版本號碼1,裡面包含一個 application: ninenines,extended_start_script 告訴 relx 要建立一個可啟動 application 的 script,下一行 sys.config 代表可指定 erlang vm 的起始參數,
{release, {ninenines, "1"}, [ninenines]}.
{extended_start_script, true}.
{sys_config, "rel/sys.config"}.
{overlay, [
{mkdir, "log"},
{copy, "rel/vm.args",
"releases/\{\{release_name\}\}-\{\{release_version\}\}/vm.args"}
]}.
參考文件 Build Erlang releases with erlang.mk and relx
rebar
編譯與安裝
下載 rebar source code
git clone https://github.com/basho/rebar.git編譯
cd rebar
./bootstrap產生出 rebar 執行檔後,可以將 rebar 複製到任何地方,都可以使用。我們可以將 rebar 複製到 /usr/local/bin 或是 ~/bin 目錄,放在隨時可使用到的 PATH 裡面,就完成 rebar 的安裝了。
直接下載 rebar
因為 rebar 是完全由 erlang 撰寫的,而且有整合成一個獨立的 escript,我們也可以直接下載編譯好的 rebar http://cloud.github.com/downloads/basho/rebar/rebar ,然後就能使用了。windows
把在 linux 環境編譯出來的 rebar 複製到 windows 環境,把 rebar.cmd 與 rebar 放在 windows 的 PATH 路徑中可以存取到的地方,就可以直接使用 rebar 了。
測試專案
mkdir myapp
建立專案目錄rebar create-app appid=myapp
產生專案的檔案骨架
完成後會看到一個 src 目錄,裡面有三個檔案:myapp.app.src、myapp_app.erl、myapp_sup.erlrebar compile
編譯 myall project,完成後會產生 ebin 目錄,也會得到一個 OTP 專案檔 myapp.apprebar clean
清除編譯結果
命令列的參數
在開發過程中,最常用的功能有
- 編譯
- 單元測試和覆蓋分析
- 靜態分析(通過Dialyzer和Xref)
- 生成文檔
- 依賴管理
Rebar commands 提供了指令與參數列表
常見指令 | description |
---|---|
compile | 編譯 |
eunit | 執行 eunit |
doc | 使用 edoc 產生文件 |
clean | 清除所有生成的資料 |
一般指令 | description |
---|---|
check_deps | 檢查 rebar.config 的 dep libs |
create | 建立專案,必須要給予 template 的設定 |
create-app | 根據 simpleapp.template 建立 app 專案 |
create-lib | 根據 simplelib.template 建立 OTP library |
create-node | 根據 simplenode.template 建立一個 prototypical OTP embedded system |
ct | 執行 common_test suites |
delete-deps | 刪除依賴的專案原始碼 |
escriptize | 以 ebin 目錄的 beam files 產生 escript 的執行檔 |
generate | 使用 reltool 建立一個embedded system |
generate-upgrade | 產生 upgrade package |
get-deps | 根據 rebar.config 取得依賴的專案原始碼 |
list-deps | 依賴的專案列表 |
update-deps | 更新依賴的專案原始碼 |
xref | 使用 xref 分析依賴 |
compile 支援的 source code 格式
source file | destination file | description |
---|---|---|
src/*.erl | ebin/*.beam | erlang source |
src/*.app.src | ebin/*.app | otp application |
c_src/*.c | priv/ |
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 source code (需要額外安裝LFE) |
src/*.peg | ebin/*.beam | Neotoma PEG 語法 source code (需要額外安裝Neotoma) |
src/*.proto | ebin/_pb.beam, include/_pb.hrl | Protocol Buffers 參數(需要額外安裝protobuffs) |
rebar.config 設定的選項
命令 | 設定的選項 | description |
---|---|---|
compile | erl_first_files | 需要提前編譯的erlang源文件(例如behavior模塊) |
compile | erl_opts | 編譯器支援的其他設定,請參閱文件 |
compile | mib_first_files | 需要提前編譯的mib文件列表 (例如, mib 文件中import部分的引用的RFC文件 |
compile | src_dirs | 列出其他包含erlang源文件的目錄 |
compile | erlydtl_opts | erlydtl 更多的支援的設定 ErlyDTL Templates |
clean | clean_files | 需要在clean步驟刪除的文件列表,列出那些需要clean指令刪除的其他模塊的文件 |
doc | edoc_opts | edoc 支援的指令 |
eunit | eunit_opts | eunit支援的指令 |
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支持的選項 |
目錄結構
rebar 遵循 OTP 的建議,包含了下列的資料夾:
- src
- ebin
- priv
- include
- test: eunit test source code
- c_src: C 語言寫的 Port Driver
Testing
rebar 支援 eunit 與 common test 兩種 testing frameworks。
首先撰寫一些 eunit 測試的程式碼,在 apps/myapp/src/myapp_app.erl 的 -export 跟 程式的最後面,增加兩段 -ifdef(TEST) 到 -endif 的測試區塊。
-module(myapp_app).
-behaviour(application).
%% Application callbacks
-export([start/2, stop/1]).
-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").
-endif.
%% ===================================================================
%% Application callbacks
%% ===================================================================
start(_StartType, _StartArgs) ->
myapp_sup:start_link().
stop(_State) ->
ok.
-ifdef(TEST).
simple_test() ->
ok = application:start(myapp),
?assertNot(undefined == whereis(myapp_sup)).
-endif.
因為直接執行 rebar eunit,連帶會對 deps 進行 eunit 的測試,所以增加 skip_deps 參數,只針對我們自己寫的程式進行測試。
rebar compile eunit skip_deps=true
如果要檢查 code coverage 的統計資料,我們必須在 rebar.config 增加以下設定
{cover_enabled, true}.
再執行一次 rebar compile eunit skip_deps=true ,就可以看到 code coverage analysis 結果寫在 apps/myapp/.eunit/index.html 檔案裡面。
其它
有關 deps, 建構 release package 以及升級的問題,就放在下一篇文章裡面說明。
沒有留言:
張貼留言