Rob*_*loi 4 erlang preprocessor
在最近的Erlang R14中,inets的文件httpd.hrl
已被移除:
src/httpd.hrl
Run Code Online (Sandbox Code Playgroud)
至:
src/http_server/httpd.hrl
Run Code Online (Sandbox Code Playgroud)
在二郎的Web框架,包括使用以下指令几个地方的文件:
-include_lib("inets/src/httpd.hrl").
Run Code Online (Sandbox Code Playgroud)
因为我喜欢Erlang Web用两个版本的Erlang(R13和R14)进行编译,所以理想情况下我需要的是:
-ifdef(OLD_ERTS_VERSION).
-include_lib("inets/src/httpd.hrl").
-else.
-include_lib("inets/src/http_server/httpd.hrl").
-endif.
Run Code Online (Sandbox Code Playgroud)
即使可以通过以下方式检索ERTS版本:
erlang:system_info(version).
Run Code Online (Sandbox Code Playgroud)
这在预处理时确实是不可能的.
如何处理这些情况?解析变换是唯一的方法吗?还有更好的选择吗?
不确定你是否喜欢这个hackish技巧,但你可以使用解析变换.
让我们首先定义一个基本的解析转换模块:
-module(erts_v).
-export([parse_transform/2]).
parse_transform(AST, _Opts) ->
io:format("~p~n", [AST]).
Run Code Online (Sandbox Code Playgroud)
编译它,然后您可以在要使用它的模块中包含两个标头.这应该给出以下内容:
-module(test).
-compile({parse_transform, erts_v}).
-include_lib("inets/src/httpd.hrl").
-include_lib("inets/src/http_server/httpd.hrl").
-export([fake_fun/1]).
fake_fun(A) -> A.
Run Code Online (Sandbox Code Playgroud)
如果您使用的是R14B并进行编译,那么您应该将模块的抽象格式看起来像这样:
[{attribute,1,file,{"./test.erl",1}},
{attribute,1,module,test},
{error,{3,epp,{include,lib,"inets/src/httpd.hrl"}}},
{attribute,1,file,
{"/usr/local/lib/erlang/lib/inets-5.5/src/http_server/httpd.hrl",1}},
{attribute,1,file,
{"/usr/local/lib/erlang/lib/kernel-2.14.1/include/file.hrl",1}},
{attribute,24,record,
{file_info,
[{record_field,25,{atom,25,size}},
{record_field,26,{atom,26,type}},
...
Run Code Online (Sandbox Code Playgroud)
这告诉我们的是,我们可以使用两个标头,并且有效的标头将自动包含在内,另一个标头会出错.我们需要做的就是删除{error,...}
元组并获得有效的编译.为此,请修复parse_transform模块,使其如下所示:
-module(erts_v).
-export([parse_transform/2]).
parse_transform(AST, _Opts) ->
walk_ast(AST).
walk_ast([{error,{_,epp,{include,lib,"inets/src/httpd.hrl"}}}|AST]) ->
AST;
walk_ast([{error,{_,epp,{include,lib,"inets/src/http_server/httpd.hrl"}}}|AST]) ->
AST;
walk_ast([H|T]) ->
[H|walk_ast(T)].
Run Code Online (Sandbox Code Playgroud)
这将删除错误包括,只有它在您想要的精确模块上.其他凌乱的包括应该像往常一样失败.
我没有在所有版本上测试过这个,所以如果它们之间的行为发生了变化,这将无法正常工作.另一方面,如果它保持不变,这个parse_transform将是版本无关的,代价是需要订购模块的编译顺序,这对于Emakefiles和rebar来说非常简单.
归档时间: |
|
查看次数: |
795 次 |
最近记录: |