配置文件

在任何项目中,总会有一组根据运行的任务或运行任务的人员角色而期望的选项。

例如,在 Erlang 项目中,最常见的例子是仅在测试运行时所需的依赖项,例如模拟库或特定的测试工具或框架。

Rebar3 通过 *配置文件* 的概念解决了这些需求。配置文件是一组仅在一个特定上下文中使用的配置设置,覆盖或补充常规配置。它们的目的是能够支持多种开发用例,同时保持操作的可重复性,并且无需使用外部工具或环境变量来完成这些工作。

可以通过三种不同的方式指定运行的配置文件

  1. 调用 rebar 为 rebar3 as <profile> <command>rebar3 as <profile1>,<profile2> <command>
  2. 通过给定的 Rebar3 命令。例如,eunitct 命令 *始终* 会将 test 配置文件添加到运行中。
  3. REBAR_PROFILE 环境变量

任何这些形式(甚至同时使用所有形式)都会让 Rebar3 知道它应该以其中一个特殊配置文件运行,并相应地修改其配置。

配置文件配置可以在主 rebar.config 文件中这样指定

{profiles, [{ProfileName1, [Options, ...]},
            {ProfileName2, [Options, ...]}]}.

例如,一个仅在测试运行时添加 meck 依赖项的测试配置文件可以定义为

{profiles, [{test, [{deps, [meck]}]}]}.

任何配置值都可以放入配置文件中,包括插件、编译器选项、发布选项等等。

示例

一个更完整的示例可能如下所示

{deps, [...]}.
{relx, [
    ...
]}.

{profiles, [
    {prod, [
        {erl_opts, [no_debug_info, warnings_as_errors]},
        {relx, [{dev_mode, false}]}
    ]},
    {native, [
        {erl_opts, [{native, {hipe, o3}}]}
    ]},
    {test, [
        {deps, [meck]},
        {erl_opts, [debug_info]}
    ]}
]}.

因此,这样的项目有 *四个* 不同的配置文件

  1. default,所有运行的事实上的配置文件,对应于整体 rebar.config 文件

  2. prod,在这种情况下,可能用于生成没有符号链接的完整版本,并使用更严格的编译器选项

  3. native,强制使用 HiPE 编译,以加快数学代码的执行速度

  4. test,加载模拟库并在测试运行期间将调试信息保留在文件中。

这些可以在多种方式中组合。以下是一些运行示例

  1. rebar3 ct:将运行项目的通用测试套件。应用的配置文件顺序为 default,然后是 test,因为 ct 要求使用 test 配置文件。

  2. rebar3 as test ct:将与之前相同。配置文件仅应用一次。

  3. rebar3 as native ct:将以原生模式运行测试。配置文件的顺序将是 default,然后是 native,最后是 test(由运行的命令最后指定)。

  4. rebar3 as test,native ct:将与上述类似,但略有不同。应用配置文件时,Rebar3 首先扩展所有配置文件,并按正确的顺序应用它们。因此,此处的顺序将是 default,然后是 test,然后是 native。最后一个 test 配置文件(因为 ct 命令)被省略,因为它已经应用过了。这与调用 rebar3 as native ct 并不完全等效,因为如果 testnative 配置文件都设置了冲突的选项,则配置文件顺序变得很重要。

  5. rebar3 release 将仅以 default 配置文件构建版本。

  6. rebar3 as prod release 将构建不带开发模式的版本,并使用更严格的编译器选项。

  7. rebar3 as prod, native release 将与上一个命令一样构建版本,但同时也将模块编译为原生模式。

  8. rebar3 as prod release 以及环境中的 REBAR_PROFILE=native,将与上一个命令一样构建版本,但 native 将在 prod 之前应用。

因此,配置文件的应用顺序为

  1. default
  2. REBAR_PROFILE 值(如果有)
  3. 命令行 as 部分中指定的配置文件
  4. 每个单独命令指定的配置文件

因此,配置文件是一种以上下文方式指定配置子集的可组合方法。

📘

锁定依赖项

rebar.config 最顶层(default 配置文件)列出的依赖项将保存到 rebar.lock 中。其他依赖项不会被锁定。

如果有人想要“锁定生产环境”(意味着使用与生产相关的配置文件),答案是保留默认配置文件并使用 版本发布,它会生成可随时重用的已编译工件。

选项合并算法

通常很难尝试自动合并所有配置选项。不同的工具或命令会以不同的方式期望它们,作为元组列表、proplist 或键值对,以转换为某种字典。

为了尽可能支持最通用的形式,Rebar3 将它们视为 proplist 和元组列表的松散组合。这意味着以下所有选项都被视为具有键 native

  • native
  • {native, {hipe, o3}}
  • {native, still, supported}

即使其中一些可能不受工具支持。例如,Erlang 编译器支持将宏定义为 {d, 'MACRONAME'}{d, 'MACRONAME', MacroValue},但不支持 d 单独使用,但它确实支持 native{native, {hipe, o3}}

Rebar3 正确支持所有这些形式并以函数方式合并它们。让我们以以下配置文件为例

{profiles, [
    {prod, [
        {erl_opts, [no_debug_info, warnings_as_errors]},
    ]},
    {native, [
        {erl_opts, [{native, {hipe, o3}}, {d, 'NATIVE'}]}
    ]},
    {test, [
        {erl_opts, [debug_info]}
    ]}
]}.

以不同的顺序应用配置文件将产生不同的 erl_opts 选项列表

  • rebar3 as prod,native,test <command>[debug_info, {d, 'NATIVE'}, {native, {hipe, o3}}, no_debug_info, warnings_as_errors]
  • rebar3 as test,prod,native <command>[{d, 'NATIVE'}, {native, {hipe, o3}}, no_debug_info, warnings_as_errors, debug_info]
  • rebar3 as native,test,prod <command>[no_debug_info, warnings_as_errors, debug_info, {d, 'NATIVE'}, {native, {hipe, o3}}]
  • rebar3 as native,prod,test <command>[debug_info, no_debug_info, warnings_as_errors, {d, 'NATIVE'}, {native, {hipe, o3}}]

请注意,最后应用的配置文件产生列表中的第一个元素,并且每个配置文件列表中的元素将根据其键进行排序。

这将允许 Rebar3 命令按正确的顺序获取元素,同时仍然支持需要许多元素共享相同键的多值列表(例如 [{d, 'ABC'}, {d, 'DEF'}],它们是两个独立的宏!)。不支持重复元素的命令可以在处理第一个元素后停止处理它们,而那些从它们构建字典(或映射)的命令可以选择按原样插入它们,或者可以先安全地反转列表(如果处理的最后一个元素成为映射中的最终元素)。

所有配置文件合并规则都是以这种安全的方式处理的。插件编写者应该了解这些规则并相应地进行规划。

请注意,在实践中,Erlang 编译器与 debug_infono_debug_info 并不兼容(这甚至不是一个真正的选项,而是由 Rebar3 添加的)。Rebar3 做了一些魔法来消除这些特定值以满足编译器的要求,但不会将此礼貌扩展到所有工具。设计插件以使用 {OptionName, true|false} 通常是一个好主意。

🚧

依赖项和配置文件

依赖项将始终使用应用于其配置的 prod 配置文件进行编译。任何依赖项都不会使用其他(当然除了 default 之外)配置文件。即使它们配置为 prod,依赖项仍将被获取到其声明下配置文件的配置文件目录中。例如,顶层 deps 中的依赖项将在 _build/default/lib 下,而 test 配置文件下的依赖项将被获取到 _build/test/lib。两者都将使用应用的 prod 配置文件配置进行编译。

上次修改时间:2021 年 5 月 6 日:接受审阅者建议 (8bc6eb4)