rebar3 自定义编译插件攻略

插件任务:

在用户执行rebar3 compile时,自动运行插件自定义的逻辑。

增加钩子:

在顶层目录的rebar3.config中增加配置(provider hooks的写法)

{provider_hooks, [       
	{pre, [{compile, {auto_config, compile}}]}
]}.

意为 rebar3 compile命令前,自动执行 rebar3 auto_config compile 指令

或者 shell hooks 的写法:
{pre_hooks, [“win32”, compile, “rebar3 auto_config compile”]}

新建插件文件:

在新建插件的目录下执行:
rebar3 new plugin 插件名字
输出为:

===> Writing rebar3_auto_config_plugin/src/rebar3_auto_config_plugin.erl 
===> Writing rebar3_auto_config_plugin/src/rebar3_auto_config_plugin_prv.erl 
===> Writing rebar3_auto_config_plugin/src/rebar3_auto_config_plugin.app.src 
===> Writing rebar3_auto_config_plugin/rebar.config 
===> Writing rebar3_auto_config_plugin/.gitignore 
===> Writing rebar3_auto_config_plugin/LICENSE 
===> Writing rebar3_auto_config_plugin/README.md

_prv文件简介:

文件中有三个回调需要我们实现:

  • init(State) - {ok, NewState},进行插件设置。
  • do(State) - {ok, NewState} | {error, Error},执行实际的工作。
  • format_error(Error) - 错误发生时打印错误。

插件设置的内容有:

  • name:任务的名称。 module:任务的实现模块。
  • bare:用户是否可以运行任务。应该设置为true。
  • deps:依赖项列表,不需要包含依赖项的依赖项。[dep | {namespace, dep}]
  • desc:任务描述,rebar3帮助使用
  • short_desc:任务的一行简短描述
  • example:任务用法示例,例如“rebar3 my-provider args”
  • opts:执行任务的选项列表。形式为 {Key, $Character, ‘StringName’, Spec, HelpText},其中:
    • Key 是一个原子,用于通过
      {Args, _} = rebar_state:command_parsed_args(State)
      Arg = proplists:get_value(Key, Args)
      获取选项值;
    • $Character 是选项的缩写形式。如果命令要作为 -c Arg 输入,则Character 应该为 c
    • Spec 可以是类型(atom、binary、boolean、float、integer或string)、默认的类型({Type、Val})或 undefined。
  • profiles:配置文件。默认为 [default]。
  • namespace:注册命名空间。默认为 default。

添加命名空间:

在 rebar3_auto_config_plugin_prv 文件 init函数中,增加namespace的定义,修改后代码如下:

Provider = providers:create([             
	{name, ?PROVIDER},                        
	{namespace, auto_config},   
	......

命名空间的作用是避免?PROVIDER和别的插件或默认命令冲突。
插件的 ?PROVIDER 定义为 compile, 那么当用户执行 rebar3 compile xxx 的时候, rebar3是执行默认的compile指令呢还是插件的指令? 为了区分这种尴尬的情况,namespace字段就排上用场了。现在我们执行 rebar3 auto_config compile XXX, rebar3就知道需要运行的是aoto_config插件指令。

DEPS的宏需要改为

-define(DEPS, [{default, app_discovery}]).

因为我们当前模块定义了新的命名空间,要使用app_discovery的话,需要指明其来源的命名空间。
如果我们没有定义新的命名空间,那么使用默认的宏定义即可。

获取执行插件的app:

-spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}.
do(State) ->     
	Apps = case rebar_state:current_app(State) of   
		undefined -> rebar_state:project_apps(State);                 	
		AppInfo -> [AppInfo]            
	end,     
	[do_some_thing(AppInfo) || AppInfo <- Apps],     
	{ok, State}.

在 do_some_thing 中实现插件的功能即可。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值