erlang——reltool配置

reltool配置及使用简介

reltool需要的配置文件通常是这样的:

{sys,
 [
  %% Global config
  {lib_dir, LibDir}
  
  {rel, RelName1, RelVsn1, [AppList]},
  {rel, RelName2, RelVsn2, [AppList]},
  {boot_rel, RelName1},

  {incl_cond, InclCond},
  {mod_cond, ModCond},
  {app_file, AppFile},

  {incl_sys_filters, InclSysFilter},
  {excl_sys_filters, ExclSysFilter},
  {incl_app_filters, InclAppFilter},
  {excl_app_filters, ExclAppFilter},
  {incl_archive_filters, InclArchFilter},
  {excl_archive_filters, ExclArchFilter},

  %% App config
  {app, AppName1, [{incl_cond, InclCond}, {mod_cond, ModCond}, {lib_dir, LibDir}]},
  {app, AppName2, [{incl_cond, InclCond}, {mod_cond, ModCond}, {lib_dir, LibDir},{mod, ModName, [{incl_cond,InclCond}]}
]},
  %% Module config
  {mod, ModName, [{incl_cond, InclCond}]}
  …
 ]
}.
整个配置文件可分为全局配置(或者称为sys配置,以下统称为全局配置),application配置以及module配置。部分配置项可同时出现在全局配置,application配置,module配置中,例如incl_cond。同时出现在几个部分的配置项,其优先级为module最高,application其次,全局最低。

使用reltool完成打包,通常会按顺序执行下面几个命令:

%% 读配置文件
{ok, Config} = file:consule("reltool.config").
%% 根据配置文件生成目标系统的规格("动作")
{ok, Spec} = reltool:get_target_spec(Config).
%% release制作与打包
reltool:eval_target_spec(Spec, code:root_dir(), rel).
如果是通过rebar打包,通常是这么几个步骤:

1. 执行命令生成reltool配置文件等其他相关文件   ./rebar create-node nodeid=Node 

2. 按需修改配置及相关文件

3. 执行命令完成release制作与打包   ./rebar generate

incl_cond配置项

打包后最终会包含哪些application,与此相关的主要配置项是incl_cond。

先来看几个例子:有三个应用分别取名app_a,app_b,app_c,每个应用都有三个模块,分别为a1,a2,a3;b1,b2,b3;c1,c2,c3。其中a1模块会调用b1模块的导出函数,b2模块会调用c2模块的导出函数。另外app_a,app_b,app_c都会依赖stdlib和kernel,此外,app_a还会依赖otp的compiler。

其目录结构为:

编写不同的配置并打包到rel目录中。

配置1:

{sys,
 [
  {lib_dirs, ["./"]},
  {rel, "test", "1",
   [kernel, stdlib, compiler, app_a
   ]},
  {boot_rel, "test"},
  {incl_cond, include},
  {mod_cond,app},

  %%其他配置项省略
  ...
 ]
}.
最终打包的结果是:所有的app均被打包,包括app_a,app_b,app_c,以及otp所有的系统应用。

配置2:

{sys,
 [
  {lib_dirs, ["/"]},
  {rel, "test", "1",
   [kernel, stdlib, compiler, app_a
   ]},
  {boot_rel, "test"},
  {incl_cond, derived},
  {mod_cond, all},
  {app, app_a, [{incl_cond, include}]},
  ...
 ]
}.
最终打包的结果是:除了app_a,app_b,app_c外,还包含了一部分otp应用,如stdlib,kernel,crypto等。

配置3:

{sys,
 [
  {lib_dirs, ["./"]},
  {rel, "test", "1",
   [kernel, stdlib, compiler, app_a
   ]},
  {boot_rel, "test"},
  {incl_cond, exclude},
  {mod_cond, all},
  {app, stdlib, [{incl_cond, include}]},
  {app, kernel, [{incl_cond, include}]},
  {app, compiler, [{incl_cond, include}]},
  {app, app_a, [{incl_cond, include}]},
  {app, app_b, [{incl_cond, include}]},
  ...
 ]
}.
最终打包结果为:仅包含了stdlib,kernel,compiler,app_a,app_b这几个应用。

总结:incl_cond可设置的值包括include,exclude,derived。

include:这个很简单,就是应用需要被包含打包。所以在配置1中,由于app均未设置incl_cond,即使用全局incl_cond配置项的值(include),因此所有的应用均被打包。

exclude:这个也好理解,就是不需要包含或者排除。对于配置3,只有几个application指定为include,其余的均使用全局的配置,因此结果也是显而易见的。

derived:这个是指如果被其他指定为include的app所间接使用,那么也需要被打包。那么怎么理解被其他app所使用?erlang又是怎么判断一个application将使用另一个application呢?reltool在打包的时候,通过xref分析所有module调用外部module的导出函数,而module可理解为是属于某个application的,这么一来,便可以知道application都间接使用了哪些其他的application。在配置2中,尽管只有app_a设置为include(app_b和app_c的incl_cond值最终为derived),但是由于模块a1会调用模块b1的导出函数,模块b2会调用模块c2的导出函数,即app_b会间接被app_a所使用,app_c又会间接被app_b所使用,因此app_a,app_b,app_c最终都将被打包,同样stdlib,kernel也间接使用了hipe,crypto,因此相关app也会被打包,其他没有被间接使用的则不会被打包。

=======================================================

补充:reltool打包的时候怎么找到所有的application的?全局配置中有个lib_dirs,app的配置中有个lib_dir,有必然联系吗?两个都需要配置吗?

实际上,reltool在打包过程中,首先根据全局配置lib_dirs指定的路径,以及root_dir(该配置项通常不需要配置,默认为code:root_dir()下的lib目录,即安装是otp自带应用的目录位置)指定的路径,罗列出在这些路径下所有的application。然后解析配置文件中的application配置部分,未出现在之前罗列出的application则进行添加,如果已存在,则按需更新路径。因此对于配置1,最终打包结果包含所有otp自带的application也就不难理解了。


mod_cond配置项

与模块包含相关的配置项就是mod_cond,这个配置项可设置的值包括:

derived:与incl_cond中的derived等同,即只有被其他明确为include的模块调用时将被包含打包。

ebin:ebin目录下所有的模块加上被其他明确为include的模块所调用的模块。

app:app文件中指定的模块加上被其他明确为include的模块所调用的模块。

all:所有模块。

mod_cond配置项相对较容易理解,但有一点需要注意:如果将配置1中mod_cond的值修改为derived,最终打包的结果是:所有的应用都包含,但是所有的应用的ebin目录下仅有一个.app文件,任何beam都未被打包,因为所有application的mod_cond最终设置为derived,也就是说没有哪个模块是明确设置为include。因此所有的模块都不会被打包。

另外,当incl_cond设置为derived时,mod_cond配置项会对app的包含关系有一定的影响。例如将前面的配置2做些修改。

配置4:

{sys,
 [
  {lib_dirs, ["./"]},
  {rel, "test", "1",
   [kernel, stdlib, compiler, app_a
   ]},
  {boot_rel, "test"},
  {incl_cond, derived},
  {mod_cond, derived},
  {app, app_a, [{incl_cond, include}, {mod_cond, all}]},
  ...
 ]
}.
最终打包后发现app_c未被打包。

解释:对于app_a,mod_cond最终为all,即所有模块都将被打包;而对于app_b,它的mod_cond和incl_cond最终都为derived,但是app_a的a1模块会调用b1,因此该应用会被打包,但是只有b1模块;对于app_c,它的mod_cond和incl_cond最终也为derived,仅管app_b的b2会调用c2,但是app_b只有b1会被打包,b2不会被打包,所以app_c的所有模块最终是不被间接使用的,因而该application也是不被间接使用的,它也就不会被打包。


rel配置项

rel配置项内容与release resource file中的内容差不多,描述release的名称,版本,以及release中包含的application,以及这些application的启动类型。

这里需要注意:当app的incl_cond最终为derived时,如果该app又出现在了rel配置项中,那么这个application也还是会被打包。例如对前面的配置4做些修改,将app_c加到rel中,那么最终app_c也被打包了。

另外,如果某个app的incl_cond最终为exclude,而该app又出现在了rel中,那么打包就会出错。例如把配置3中的{app, compiler, [{incl_cond,include}]}一行删除,打包就出现如下错误。


总结

从前面可以看到reltool的配置非常灵活,不同的场景可以设置不同的值来满足需要,比如设置mod_cond为derived保证不需要的模块都不打包以此保证最终的镜像足够精简,incl_cond设置为derived让reltool自动分析application之间的依赖关系等。但是灵活的同时可能会出现很多未知的问题,因此对于一般使用者,推荐将mod_cond设置为all,incl_cond设置为exclude,需要打包的app都手动添加对应的app配置项。

转载于:https://my.oschina.net/hncscwc/blog/355333

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值