2010-01-06 42 views
4

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

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}}]}],[]} 

我在做什么错?

回答

4

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

今天没有办法在表单列表上运行预处理器。您将不得不明确包含该文件并进行宏处理。从表单和文件中提取一些输入信息似乎也有点奇怪。

+0

感谢。我被这个文件误导了。所以基本上我可以1)自己获取标题,将它们解析为表单,并用它们替换属性,或者2)将我的表单打印到源文件,然后编译。 – Zed 2010-01-07 07:29:31

+0

就是这样。或者修复epp。 :-) – rvirding 2010-01-07 19:40:02

+0

仅供参考,有一个模块用于对erl_scan返回的令牌进行预处理:https://github.com/evanmiller/aleppo – Emiller 2010-12-13 22:02:53

0

我们这样做是为了只为记录的项目,但它需要一个几件事情:

  1. 你必须有一个模块在运行时加载其中有你需要包括.hrl-文件(梁对于这个模块也必须在路径上可用)。
  2. 该模块必须使用调试信息进行编译(+debug_info到编译器或[debug_info]作为c/2的选项参数)。
  3. 您必须自己将.hrl记录定义插入到表单中。

这里是如何做到这一点:

首先创建一个模块,其中包括.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文件)。

这样做的方式当然可以用于记录属性以外的其他属性(甚至是.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}}]}]}]. 
+0

感谢分享。这是一个有趣的“解决方法”的问题:) – Zed 2010-01-12 10:32:59

+0

是的!这很好,因为它总是提供最新版本的记录,即使.hrl文件有变化(因为my_hrl.erl得到重新编译)。 – 2010-01-29 19:31:14