自定义编译器模块

这是 Rebar3 3.7.0 中的一个新功能,用于编写要与之一起使用的自定义编译器。当您拥有想要与 Erlang 资源一起构建的不同语言的文件时,此功能非常有用。从 Rebar3 3.14.0 开始,该接口得到了增强,可以更好地跟踪有向无环图 (DAG) 中的文件,这使您可以注释构建工件,并允许 Rebar3 跟踪应用程序之间的依赖关系。

此接口目前在内部用于 .xrl.yrl.mib 文件。很少有插件尝试过它。

🚧

这是一个不稳定的接口

由于我们还没有很多插件作者尝试过此接口,因此将其标记为不稳定,并且可能会发生更改。

我们正在寻求贡献者的帮助,以便在将其标记为稳定之前进一步稳定它。如果您愿意联系我们并帮助迭代 自定义编译器插件 中提供的功能,则应使用此功能。

您的自定义编译器可能需要更复杂的内容。例如,此接口提供的工具不足以构建使用 mix 作为构建工具运行的项目,并且该插件使用 自定义编译器插件

当前接口

定义了以下回调函数

%% specify what kind of files to find and where to find them. Rebar3 handles
%% doing all the searching from these concepts.
context(AppInfo) ->
    %% Mandatory Fields
      %% directories containing source files
    #{src_dirs     => ["/path/to/src/"],
      include_dirs => ["/path/to/includes/"],
      src_ext      => ".erl",
      out_mappings => [{".beam", "/path/to/ebin"}],
    %% Optional Fieldsstate passed to dependencies callback
      dependencies_opts => term()}.                 % optional, v3.14+

%% Define which files each of the files depends on, including includes and whatnot.
%% This is then used to create a digraph of all existing files to know how to propagate
%% file changes. The Digraph is passed to other callbacks as `G' and annotates all files
%% with their last changed timestamp
%% Prior to 3.14, the `State' argument was not available.
dependencies("/path/to/file.erl", "/path/to/",
             ["/path/to/all/other_sources/", ...], State) ->
    ["path/to/deps.erl", ...].

%% do your own analysis aided by the graph to specify what needs re-compiling.
%% You can use this to add more or fewer files (i.e. compiler options changed),
%% and specify how to schedule their compilation. One thing we do here for
%% Erlang files is look at the digraph to only rebuild files with newer
%% timestamps than their build artifacts (which are also in the DAG after the
%% first build) or those with compiler options that changed (the
%% compile_and_track callback lets you annotate artifacts)
needed_files(G, ["/path/to/all/files.erl", ...], [{".beam", "/path/to/ebin"}], AppInfo) ->
    %% the returned files to build essentially specify a schedule and priority with special
    %% option sets
     %% Files that _must_ be built first like those in parse transforms, with
     %% different build options
    {{["/top/priority/files.erl"], CompilerOpts},
     %% {Sequential, Parallel} build order for regular files, with shared
     %% compiler options
     {{["/path/to/file.erl", ...], ["other/files/mod.erl", ...]}, CompilerOpts}}.

%% Compilation callback with the ability to track build artifacts in the DAG itself.
%% Introduced in 3.14. Prior to this version, refer to `compile/4'.
compile_and_track("/path/to/file.erl", [{".beam, "/path/to/ebin"}],
                  AppOptDict, CompilerOpts) ->
    %% Successfully built a file, tying it to artifacts with optional metadata
    {ok, [{"/path/to/file.erl", "path/to/ebin/file.beam", Metadata}]} |
    %% Successfully built a file, but it has compiler warnings
    {ok, [{"/path/to/file.erl", "path/to/ebin/file.beam", Metadata}],
         ["Some compiler warning"]} |
    %% Failed build
    {error, ["error strings"], ["warning strings"]} | error.

%% A simpler compilation mechanism which does not track build artifacts into the
%% DAG for the compiler. Change for built files must be figured out from files on
%% disk or other storage.
compile("/path/to/file.erl", [{".beam", "/path/to/ebin"}],
        AppConfig, CompilerOpts) ->
            ok
          | {ok, ["Some compiler warning"]}
          | {ok, ["error strings"], ["warning strings"]}.

%% Just delete files however you need to
clean(["/path/to/file"], AppInfo) -> _.

将编译器模块初始化为插件

在注册 自定义编译器插件 的同一位置注册编译器模块

%% Note: the name of the module matches the name of the plugin application
-module(my_compiler_plugin).
-export([init/1]).

%% Called when Rebar3 first boots, before even parsing the arguments
%% or commands to be run. Purely initiates the provider, and nothing
%% else should be done here.
-spec init(rebar_state:t()) -> {ok, rebar_state:t()}.
init(State) ->
    %% Optional:
    %% Provider = providers:create([Options]),
    %% State1 = rebar_state:add_provider(State, Provider),

    %% This adds the new compiler module:
    State1 = rebar_state:append_compilers(State, [my_compiler_mod]),
    %% If needing the new compiler module to take precedence over
    %% other ones (i.e. generating .erl files from another format):
    State2 = rebar_state:prepend_compilers(State1, [translator_mod]),
    {ok, State2}.
上次修改时间:2024年1月11日:更新 custom_compiler_modules.md (3c0a8ba)