背景

我们用rebar3编译经常遇到bad record的问题,同事给record加了字段,然后我这边更新下来,不clean,直接compile,然后部分模块出现bad record,有些不会。直观感觉就是有些代码include的头文件改变了,但是代码并没有编译引起的。

分析

通过阅读了rebar3的rebar_erlc_compiler.erl之后,发现.rebar3/erlcinfo是基于Erlang的digraph模块(有向图)来实现。如果我的头文件循环引用会不会有什么奇怪的事情?然后我就开始做测试。

测试

测试代码下载

创建个app,将下载的代码复制到src和include里面,然后编译。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ rebar3 new app name=test
$ mkdir test/include
$ mv *.hrl test/include/
$ mv *.erl test/src/
$ cd test
$ rebar3 compile
$ erl -pa _build/default/lib/test/ebin/ -s main start -s init stop
a b
a b
a b
$ #修改 include/a.hrl,将a改为b
$ rebar3 compile
$ erl -pa _build/default/lib/test/ebin/ -s main start -s init stop
b b
b b
a b

出现问题的main3只include了b.hrl。

b include了a,a又include了b,然后b指向b。单单include了b,a的改动是不会被rebar3感知,最后就没编译了,但是实际要编译才对。

解决办法

  • 避免循环引用
  • 显性同时include,让rebar3知道