reltool用戶指南

說明,最近比較忙,沒有太多時間更新blog,請各位朋友諒解.

尋找俺的朋友,可以gtalk : litaocheng[at]gmail.com 或者 twitter : @litaocheng

這篇文章,應該是我寫的最久的一篇,請各位多實踐.

 

 

reltool使用指南

Author: litaocheng
Mail: [email protected]
Revision: 1
Date: 2009.10.28

1   概述

reltoolErlang 提供的 release 管理工具. 我們依據 Erlang/OTP 開發的 application, 最後需要發佈,這時需要使用 reltool 幫我們生成最終的 release, 也稱爲 target system. 同時 reltool 可以分析 application 的依賴關係,幫助我們正確的發佈應用.

reltool 包括一個基於 wx 的 GUI 前端(wxWidgets erlang bind), 其可以用來查看 application 的依賴關係,可以查看模塊的依賴關係,可以查看源代碼. reltool 也提供使用命令來生成自定義的發佈包.

1.1   適用範圍和目的

本文檔主要介紹如何使用 reltool, reltool 爲 Erlang/OTP 開發環境的一部分. 本文假設讀者對Erlang相關開發比較熟悉,瞭解 Eralng/OTP 開發規範. Erlang/OTP 要求R13B02及以上版本.

1.2   瞭解更多內容

可以通過下列相關文檔瞭解更多 Erlang/OTP 開發相關信息

2   使用

前面講過, reltool 提供 GUI 和命令兩種交互方式, 本章首先簡單的介紹GUI界面相關內容, 重點是使用命令生成 release, 發佈自己的應用. 之所以重點介紹命令方式,主要基於兩個因素:

  1. 命令方式是基礎, GUI 只是提供了一個界面封裝, 本質還是調用的相關的命令
  2. GUI 目前功能還不是很完整,很多操作不支持

2.1   GUI 相關

2.1.1   System Window

通過調用 reltool:start/0,1 啓動 reltool, reltool 在啓動時,首先掃描所有的 application 和 module, 分析其相互依賴關係.隨後啓動 system window.

system window 包含四個page window (tabs):

  • Libraries
  • System settings
  • Applications
  • Releases

點擊對應的tag, 可以切換page.

system window 如下圖:



 

Librarie 窗口如下圖



 

在 library 窗口, 我們設置 reltool 將要使用的代碼. 本頁面以 tree 的形式來組織內容, 你可以點擊每行前面的標記摺疊/展開對應內容.

Library directories, Escript files 都可以進行操作. 選擇對應的項目,按住鼠標右鍵顯示對應的菜單, 移動鼠標選擇對應的菜單項,釋放鼠標右鍵.

雙擊 lib 下某個 application, 可以顯示對應的 application window.

通過 reltool GUI, 我們還可以查看很多 windows, 如 aplication 依賴圖:



 

源代碼窗口:



 

2.1.2   System Settings

Avaiable 中顯示的所有可用的 applications. 在 system page 中,我們可以設置全局的 application 包含規則, 即 incl_cond.

incl_cond 包含三種策略,我們在介紹命令方式創建release時,會詳細介紹.

3   用命令生成relase(target system)

先說一下爲自己的 application 生成 release 的步驟:

  1. 依據 Erlang/OTP 項目完成, 測試通過
  2. 定義 reltool 使用的關於最終 release 的各種配置參數 Config
  3. reltool:start_server(Config) 啓動 reltool
  4. reltool:get_target_spec/1 獲取根據 Config 產生的用來創建 target system 的一系列"動作"(Spec)
  5. reltool:eval_target_spec/3 根據 Spec 生成 target system
  6. 書寫輔助的腳本,用來生成最終的安裝包(可以爲tar包,或者zip等)

我們假設第1步,您已經完成.

生成 target system 的重點就是 config 的設置了, 讓我們詳細的描述一下 reltool 手冊中各項 config 參數.

config 可以大體分爲4種類型:

  • 基本配置
  • sys 配置
  • app 配置
  • mod 配置

其中,很多配置信息在 sys, application, mod 三個等級中均會出現,其關係爲: mod > app > sys, 即 mod 配置覆蓋 app 配置, app 配置覆蓋 sys 配置.

3.1   基本配置

  • root_dir

    Reltool 根據當前開發環境產生 target system, 因此 config 信息中勢必包含 erlang root_dir 信息.

    root_dir 指明 erlang 的當前安裝目錄(比如在 ubuntu 9.04 下, 默認爲 /usr/local/lib/erlang).本選項可以不用指定, reltool 會自動設置 root_dir.

  • lib_dirs

    除卻 $ERL_LIB 外, 指定附加的 library 目錄. 主要用來指定非 Erlang/OTP 正式發佈版本中的 application 或 library.如第三方 library, 或我們自己的 application.

3.2   sys 配置

  • erts

    指定 erts application 信息, 具體的字段參考後面介紹的 app 配置.

  • escript

    escript 腳本配置信息, 包含 escript 文件,以及對應的配置信息

  • app

    target system 中包含的 app 信息. 比如所有的 release 都要包含 kernel, stdlib, 具體的app的相關配置,輕參考後面介紹的 app level 配置

  • mod_cond

    設置 module 的包含策略. 其包含多種方式:

    • all - 表示如果某個 app 被包含,那麼其包含的所有模塊全部被包含. 假設 app 名爲 demoapp, all 不僅包含 demoapp/ebin 下的所有模塊, 同時 demoapp.app 中 modules 字段描述的所有模塊也將被包括(默認)
    • ebin - 表示 ebin 目錄下所有的模塊,以及相關的模塊會被包含
    • app - 表示 .app 描述文件,以及相關的模塊會被包含
    • derived - 表示被其他包含的模塊用到的相關模塊會被包含

    此處配置的 mod_cond 是 sys level 的配置, 控制所有的 app 中的 module 包含策略. 當然我們可以對這個信息, 在 app level 進行覆蓋.

  • incl_cond 設置 applicaion 以及 escript 的包含策略.

    其包含3種類型:

    • derived - 表示 包含 沒有明確設置 incl_cond, 同時被其他 application 直接或間接引用的application. (默認)
    • include - 表示 包含 所有沒有明確設置 incl_cond 的application
    • exclude - 表示 排除 排除沒有明確設置 incl_cond 的application

include 和 exclude 意義相反. 一個是包含沒有設置 incl_cond 的 apps, 一個是排除沒有設置 incl_cond 的 apps.

一般我們使用默認的 derived 選項,這樣保證所有相關的 application 均被包含, 不會出現 target system 中,某個模塊沒有定義的錯誤.我們可以通過前面 reltool GUI 部分介紹的 application 依賴關係圖 來了解 application 的交互相關信息.

  • boot_rel

    指定 target system 中默認啓動項 (rel), 一個target system 中可能包含很多的 release(通過 rel 來指定)

  • rel

    指定 rel 內容 (Release specific configuration), 每個 rel 定義會被映射成 rel, script 和 boot 文件,請參考 Erlang/OTP Design Principles Release

  • relocable

    指定 target system 中erl 執行時自動檢測路徑相關信息({relocable, true}), 還是硬編碼指定路徑啓動({relocable, false}). 如果 relocable 爲 false, 那麼 target system 必須首先通過 reltool:install/2 進行安裝, 如果 relocable 爲 true, target system 移動到其他目錄時,仍然可以方便的運行. {relocable, true} (默認)

  • profile 指定 tareget system 的類型, 此選項主要影響:incl_sys_filters, excl_sys_filters, incl_app_filters 和 excl_app_filters. 不同的 profile 類型, 以上4個 filters 不同.

    主要包含3種:

    • development - 開發測試模式(默認)
    • embedded - 嵌入式完整模式
    • standalone - 單獨模式,不攜帶相關的可執行文件

    在生成 target system 時, 實際上主要有兩個步驟:首先創建一個完整的文件候選列表,它包含儘可能多的文件; 隨後調用各種相關的 filter 定義,對結果進行過濾, 最後聲稱最終的 target system.

    一般情況下,我們的target system 要是一個完整的可執行的系統,因此我們許要設置 profile 爲 embedded. (當然不設置 profile, 只是修改4個相關的 filter, 也可以達到我們想要的效果)

  • app_file

    控制 app 的內容, 因爲有各種各樣的 filter, 因此最終的 target system 中包含的模塊,可能與 app 文件定義的模塊列表不一致, 本選項控制 app 的內容. 主要包含3種:

    • keep - 將 app 直接拷貝到 target system 中(默認)
    • strip - 依據 app 文件產生 target system 中的 app 文件, 並將未被包含的模塊從 app 文件中移出
    • all - 依據 app 文件產生 tarege system 中的 app 文件, 同時所有的模塊將添加到 app 文件中, 如果某個應用沒有 app 文件,那麼會自動創建一個 app 文件.
  • debug_info

    是否去除 beam 文件中的調試信息: keep 表示保持; strip 表示去除

  • incl_sys_filters

    指定一個正則表達式列表,用來表示哪些系統文件可以出現在 target system 中. 如果某個系統文件想被包括, 那麼其必須滿足 incl_sys_filters 中的某個正則表達式, 同時不能滿足 excl_sys_filters 中的任何表達式.

    比如:

    {incl_sys_filters,["^bin","^erts","^lib","^releases"]},
    

    表示 $ERL_ROOT 目錄下的 bin, erts, lib, releases 目錄均要包含.

    incl_app_filters, excl_app_filters 同 sys 相關的 filters 含義大致相同,只是用來控制 application 的包含規則.

  • excl_sys_filters

    指定一個正則表達式列表,表示哪些系統文件不可以出現在 target system 中. 默認 爲 [].

  • incl_app_filters

    指定一個正則表達式列表,表示 application 中的哪些文件可以被包含. 如果某個文件想被包含,至少要滿足正則表達式列表中的一個表達式. 默認爲 [".*"], 如果設置爲 [], 那麼 application 中的任何文件都不會被包含.

  • excl_app_filters

    指定一個正則表達式列表,表示 application 的哪些文件不可以出現在 target system 中. 默認 爲 [].

  • incl_archive_filters

    指定 application 中哪些一級子目錄包含在壓縮包中(與包含正常的目錄對應), 通過一個正則表達式列表指定要包含在壓縮包中的一級子目錄. 默認爲 [".*"]

  • excl_archive_filters

    指定一個正則表達式列表,指定 application 的哪些一級目錄不包含在壓縮包中. 如果某個目錄,匹配任何一個正則表達式,則不會包含在壓縮包中. 默認爲 ["^include$", "^priv$"]

  • archive_opts

    創建壓縮包對應的參數,在 zip:create/3 中使用, 請參考 zip module, 默認 爲 [].

3.3   app 配置

  • vsn

    指定要包含的 application 的版本, 因爲在系統中,可能存在同一應用的多個版本. 如果忽略,則使用最新版本.

  • mod

    模塊相關的配置信息. 必須包含一個模塊名稱,以及其他可選的模塊配置(參照後面 mod 配置)

  • mod_cond - 同 sys level 的同名配置含義相同

  • incl_cond - 同上

  • debug_info - 同上

  • incl_app_filters - 同上

  • excl_app_filters - 同上

  • incl_archive_filters - 同上

  • excl_archive_filters - 同上

  • archive_opts - 同上

3.4   mod 配置

  • incl_cond

    指示模塊是否被包含,其覆蓋 application 及 system 配置中的 incl_cond 信息.

    其包含3個值:

    • include - 表示本模塊將被包含
    • exclude - 表示本模塊不被包含
    • derived - 表示如果其他被包含的模塊引用本模塊,則本模塊被也被包含.
  • debug_info

    同 app 配置中 debug_info 描述.

4   例子

最後是一個實例,我們爲 erlips (erlang ip service) 生成 target system.

config (erlips.config)如下:

{sys,
   [
   {lib_dirs,["/home/litaocheng/erlang"]},
   {boot_rel, "erlips"},
   {rel, "erlips", "0.1", [kernel, stdlib, sasl, mochiweb, erlips]},
   {relocatable, true},
   {profile, embedded},
   {app_file, keep},
   {debug_info, strip},
   {mod_cond, all},
   {incl_cond, derived},

   {incl_app_filters, ["^include", "^priv", "^ebin", "^src"]},
   {excl_app_filters, []},

   {incl_archive_filters,[]},
   {excl_archive_filters,[".*"]},

   {app, kernel, [{incl_cond, include}]},
   {app, stdlib, [{incl_cond, include}]},
   {app, sasl, [{incl_cond, include}]},
   {app, erlips, [{incl_cond, include},
                   {incl_app_filters, [".*"]},
                   {excl_app_filters, ["^log", "^var", "^release"]}]},
   {app, mochiweb, [{incl_cond, include}]},
   {app, runtime_tools, [{incl_cond, include}]}
   ]
}.

我們爲一個名叫 erlips 的 application 生成 target system.

隨後執行:

> {ok, Server} = reltool:start_server([{config, "erlips.config"}]).
> {ok, Spec} = reltool:get_target_spec(Server).
> RelDir = "target_dir".
> file:make_dir(RelDir).
> ok = reltool:eval_target_spec(Spec, code:root_dir(), RelDir).
> zip:zip(RelDir ++ ".zip", [RelDir]). % 創建zip包

將生成的 zip 包拷貝到沒有安裝 Erlang 環境的電腦中, 解壓 zip 包, 隨後運行:

./bin/erl

則自動啓動 erlips 應用.

5   config type定義

下面爲 reltool 中各相關 config 的 type 定義(參考 reltool):

options()           = [option()]
option()            = {config, config() | file()}
                   | {trap_exit, bool()}
                   | {wx_debug, term()}
config()            = {sys, [sys()]}
sys()               = {root_dir, root_dir()}
                   | {lib_dirs, [lib_dir()]}
                   | {profile, profile()}
                   | {erts, app()}
                   | {escript, escript_file(), [escript()]}
                   | {app, app_name(), [app()]}
                   | {mod_cond, mod_cond()}
                   | {incl_cond, incl_cond()}
                   | {boot_rel, boot_rel()}
                   | {rel, rel_name(), rel_vsn(), [rel_app()]}
                   | {relocatable, relocatable()}
                   | {app_file, app_file()}
                   | {debug_info, debug_info()}
                   | {incl_sys_filters, incl_sys_filters()}
                   | {excl_sys_filters, excl_sys_filters()}
                   | {incl_app_filters, incl_app_filters()}
                   | {excl_app_filters, excl_app_filters()}
                   | {incl_archive_filters, incl_archive_filters()}
                   | {excl_archive_filters, excl_archive_filters()}
                   | {archive_opts, [archive_opt()]}
app()               = {vsn, app_vsn()}
                   | {mod, mod_name(), mod()}
                   | {mod_cond, mod_cond()}
                   | {incl_cond, incl_cond()}
                   | {debug_info, debug_info()}
                   | {app_file, app_file()}
                   | {incl_sys_filters, incl_sys_filters()}
                   | {excl_sys_filters, excl_sys_filters()}
                   | {incl_app_filters, incl_app_filters()}
                   | {excl_app_filters, excl_app_filters()}
                   | {incl_archive_filters, incl_archive_filters()}
                   | {excl_archive_filters, excl_archive_filters()}
                   | {archive_opts, [archive_opt()]}
mod()               = {vsn, app_vsn()}
                   | {incl_cond, incl_cond()}
                   | {debug_info, debug_info()}
rel_app()           = app_name()
                   | {app_name(), app_type()}
                   | {app_name(), [incl_app()]}
                   | {app_name(), app_type(), [incl_app()]}
app_name()          = atom()
app_type()          = permanent | transient | temporary | load | none
app_vsn()           = string()
archive_opt         = zip_create_opt()
boot_rel()          = rel_name()
app_file()          = keep | strip | all
debug_info()        = keep | strip
dir()               = string()
escript()           = {incl_cond, incl_cond()}
escript_file()      = file()
excl_app_filters()  = regexps()
excl_archive_filters() = regexps()
excl_sys_filters()  = regexps()
file()              = string()
incl_app()          = app_name()
incl_app_filters()  = regexps()
incl_archive_filters() = regexps()
incl_cond()         = include | exclude | derived
incl_sys_filters()  = regexps()
lib_dir()           = dir()
mod_cond()          = all | app | ebin | derived | none
mod_name()          = atom()
profile()           = development | embedded | standalone
re_regexp()         = string()
reason()            = string()
regexps()           = [re_regexp()] | {add, [re_regexp()]} | {del, [re_regexp()]}
rel_file()          = term()
rel_name()          = string()
rel_vsn()           = string()
relocatable         = boolean()
root_dir()          = dir()
script_file()       = term()
server()            = server_pid() | options()
server_pid()        = pid()
target_dir()        = file()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章