使用包含的头文件编译表单

时间:2010-01-06 13:18:06

标签: forms erlang compilation

我正在尝试使用包含的头文件从表单编译模块。首先,如果我在源文件中有模块,一切正常。

user.hrl

-record(user, {name :: string()}).

zed.erl

-module(zed).
-export([f/1]).
-include("user.hrl").

f(User) ->
   User#user.name.

1> compile:file(zed, [return]). 
{ok,zed,[]}
2> rr("user.hrl").
[user]
3> zed:f(#user{name = "Zed"}).
"Zed"

如果我尝试从表单编译相同的模块,我会收到一个未定义的记录错误。使用{i, Dir}和其他选项无济于事。

1> Forms = [{attribute,1,module,zed},
1>  {attribute,1,export,[{f,1}]},
1>  {attribute,1,include,"user.hrl"},
1>  {function,1,f,1,
1>      [{clause,1,
1>           [{var,1,'User'}], [],
1>           [{record_field,1,
1>                {var,1,'User'},
1>                user,
1>                {atom,1,name}}]}]}].
  ....
2> compile:forms(Forms, [return]).
{error,[{".",[{1,erl_lint,{undefined_record,user}}]}],[]}

我做错了什么?

2 个答案:

答案 0 :(得分:4)

包含文件和宏由epp(erlang预处理器)处理。 compile:forms / 1函数假定已经完成了所有预处理,因此它将{attribute,1,include,...}处理为一个未知属性。与宏相同。

今天没有办法在表单列表上运行预处理器。您必须明确包含该文件并执行宏处理。从表单中获取一些输入,从文件中获取一些输入可能看起来有点奇怪。

答案 1 :(得分:0)

我们为一个项目仅为记录做了这个,但它需要一些东西:

  1. 您必须在运行时加载一个模块,其中包含您需要的.hrl文件(此模块的梁也必须在路径上可用)。
  2. 模块必须使用调试信息(+debug_info编译到编译器或使用[debug_info]作为c/2的选项参数进行编译。
  3. 您必须自己在表单中插入.hrl-record定义。
  4. 以下是如何操作:

    首先创建一个包含.hrl文件的模块:

    -module(my_hrl).
    
    -include("my_hrl.hrl").
    
    -export([records/0]).
    
    records() ->
        {_Module, _Beam, FilePath} = code:get_object_code(?MODULE),
        {ok, {_, [{abstract_code, {_, AC}}]}} =
            beam_lib:chunks(FilePath, [abstract_code]),
        [R || {attribute, _, record, _} = R <- AC].
    

    这将为您提供一个模块,其include/0函数将为您提供该模块中所有记录的抽象代码列表(来自包含在内的.hrl文件)。

    这种方式当然可以用于除record属性之外的其他属性(甚至是.hrl文件中的函数)。

    获得记录属性列表后,只需将它们附加到表单中即可:

    Forms = [{attribute,1,module,zed},
             {attribute,1,export,[{f,1}]}]
    
            ++ my_hrl:records() ++
    
            [{function,1,f,1,
              [{clause,1,
                [{var,1,'User'}], [],
                [{record_field,1,
                  {var,1,'User'},
                  user,
                  {atom,1,name}}]}]}].