在用户执行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
文件中有三个回调需要我们实现:
插件设置的内容有:
在 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的话,需要指明其来源的命名空间。
如果我们没有定义新的命名空间,那么使用默认的宏定义即可。
-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 中实现插件的功能即可。