Xref 是一个交叉引用工具,通过分析定义的函数间的调用关系,用于查找函数、 模块、 应用程序和版本之间的依赖关系。

通俗而言,Xref 可以检查代码中函数的调用关系。比如在 moduleA 中的 funA 调用了moduleB 中的funB, 但是moduleB 中并未定义funB,此错误在代码编译期间不能被发现,但是可以通过Xref 检查。

栗子

使用reabr 创建一个application ,命名为xref_test,目录结构如下:

 1 $ tree
 2 .
 3 ├── ebin
 4 │   ├── test.beam
 5 │   ├── xref_test.app
 6 │   ├── xref_test_app.beam
 7 │   └── xref_test_sup.beam
 8 ├── rebar
 9 ├── src
10 │   ├── test.erl
11 │   ├── xref_test.app.src
12 │   ├── xref_test_app.erl
13 │   └── xref_test_sup.erl
14 └── xref.config
15  
16 2 directories, 10 files

其中 test.erl 的代码为:

1 $ cat ./src/test.erl
2 -module(test).
3 -export([start/0]).
4 start() ->
5     test_2:start().

在test module 中定义start/0  函数,其中调用了test_2:start/0 函数,但是此函数并没有定义。这种情况,必然会引发错误,但是在编译期间,并不能发现。

1 $ ./rebar com
2 ==> xref_test (compile)
3 Compiled src/xref_test_app.erl
4 Compiled src/test.erl
5 Compiled src/xref_test_sup.erl

OK,上述执行是顺利完成的。但是在运行时,必然会发生错误。

1 1> test:start().
2 ** exception error: undefined function test_2:start/0

那么,怎样才能在运行之前发现这个错误呢?Xref 就应该隆重登场了。

rebar xref 

在rebar 中,集成了xref 工具,相关的配置信息如下:

 1 {xref_warnings, false}.
 2 %% optional extra paths to include in xref:set_library_path/2.
 3 %% specified relative location of rebar.config.
 4 %% e.g. {xref_extra_paths,["../gtknode/src"]}
 5 {xref_extra_paths,[]}.
 6 %% xref checks to run
 7 {xref_checks, [undefined_function_calls, undefined_functions,
 8                locals_not_used, exports_not_used,
 9                deprecated_function_calls, deprecated_functions]}.
10 %% Optional custom xref queries (xref manual has details) specified as
11 %%     {xref_queries, [{query_string(), expected_query_result()},...]}
12 %% The following for example removes all references to mod:*foo/4
13 %% functions from undefined external function calls as those are in a
14 %% generated module
15 {xref_queries,
16  [{"(XC - UC) || (XU - X - B"
17    " - (\"mod\":\".*foo\"/\"4\"))",[]}]}.

在rebar.config 文件中,配置好这些信息,执行:

1 $ ./rebar xref
2 ==> xref_test (xref)
3 Warning: test_2:start/0 is undefined function (Xref)
4 src/test.erl:5: Warning: test:start/0 calls undefined function test_2:start/0 (Xref)
5 ERROR: xref failed while processing /Users/redink/erlang/test/xref_test: rebar_abort

这个时候,错误就能够清晰的看出来了。

xref_runner

xref_runner 是独立于rebar xref 的一个工具,支持在非rebar 组织的项目中使用xref ,友好度很高。

https://github.com/inaka/xref_runner

在rebar node 组织的Erlang release 中,可以使用xref_runner 方便的对apps 目录下的application 进行xref 检查。

 xrefr.config 定义:

 1 $ cat xrefr.config
 2 [
 3    {xref, [
 4             {config, #{dirs => ["./apps/appname/ebin"],
 5                extra_paths => [
 6                 "./deps/***/ebin"]}},
20             {checks, [
21                      undefined_functions
22                      , undefined_function_calls
23                      , locals_not_used
24                      %%, exports_not_used
25                      , deprecated_function_calls
26                      , deprecated_functions
27                      ]},
28             {xref_default, {verbose}}
29           ]
30    }
31 ].

总结

Xref 非常有用,能帮我们在运行之前尽快的发现代码的错误以及潜在的错误。

扩展阅读:

http://www.erlang.org/doc/apps/tools/xref_chapter.html

posted on 2015-05-12 18:26  _00  阅读(2793)  评论(0编辑  收藏  举报