最近看霸爷的微博([url]http://weibo.com/tchuba[/url])提到,rebar([url]https://github.com/basho/rebar[/url])是学习Erlang很好的材料,因此作为Erlang新手,自己也把源码下载下来看了下,确实发现代码写的非常优雅工整,里面的每个方法(函数)写的都很短小干练,的确可以作为写Erlang代码的范例!
那么rebar是什么呢?
如果你是Java程序员,那么你一定知道maven,maven可以用来构建java工程项目,并且提供jar包版本管理,编译,项目打包等一系列操作,而rebar就像maven一样,提供了对Erlang工程的构建,编译,依赖管理等操作(我相信随着Erlang的发展,rebar会成为标准被大家所接受)
关于rebar的下载安装以及使用,网上已经有很多例子,我也就不再赘述,那么我会说些什么呢?
1.rebar是如何执行编译的?
2.rebar执行流程是什么样的?
[color=red]--------------------------------------------------------------------------华丽分割线--------------------------------------------------------------------------[/color]
和编译相关的源文件主要有两个,它们分别是:[b]rebar_base_compiler.erl[/b] 和 [b]rebar_erlc_compiler.erl[/b],其中[b]最为核心的部分[/b]为:rebar_base_compile中的run/4方法,它包含了rebar编译的整个流程和策略
[img]http://dl.iteye.com/upload/attachment/0079/8971/41f8fd03-7c9b-388e-8995-659291b5a3dc.jpg[/img]
run方法有四个参数:
第一个参数Config表示rebar配置(关于如何初始化rebar配置以后会详说),在rebar配置中包含了编译选项(譬如是否含有debug_info);
第二个参数FirstFiles和第三个参数RestFiles都表示需要编译的Erlang源文件,但他们采用完全不同的编译策略(稍后会详述);
第四个参数CompileFn则是真正被用来编译源文件的方法
刚才我们说了,源文件分为两种:FirstFiles和RestFiles
其中对于FirstFiles采用[b]串行编译[/b],也就是说是它会按照FirstFiles中文件列出的顺序,逐个编译;
而对于RestFiles,则是[b]并发编译[/b],即会起多个子process去执行编译任务;
那么rebar为什么要这样分呢,我自己是这样理解的(一点拙见):
1.串行编译的好处是能够根据依赖关系控制源文件编译顺序,但缺点就是编译太慢,需要一个一个执行;
2.并行编译的好处就是效率高,但很显然它无法控制编译顺序;
鉴于此,rebar结合了两种编译方式,将源文件分为FirstFiles和RestFiles,然后对FirstFiles采用串行编译,对RestFiles执行并发编译(默认源文件都是并发编译(即RestFiles),需要串行编译的文件要在rebar.config文件中的erl_first_files属性中列出)
现在我们具体看看rebar串行编译的相关代码(compile_each方法)
[img]http://dl.iteye.com/upload/attachment/0079/8973/1e807d0a-9acb-306c-9d0e-e90d1485f618.jpg[/img]
这段代码比较好理解:递归编译源文件直到遍历完FirstFiles或者中间发生编译错误 (?FAIL 会抛出异常,然后中断当前操作),看完了串行编译,我们看下rebar的并行编译部分(它分为子process和父process两部分):
[b]a.子process部分(执行compile_worker方法)[/b]
[img]http://dl.iteye.com/upload/attachment/0079/8975/a5dd6856-c086-38a3-921a-6ac57d0ca051.jpg[/img]
[b]b.父process部分(执行compile_queue方法)[/b]
[img]http://dl.iteye.com/upload/attachment/0079/8977/23a5e27a-c0a9-3723-90b7-f562362756fd.jpg[/img]
[img]http://dl.iteye.com/upload/attachment/0079/8979/4bdb627d-252f-35e8-9589-0cf7219457b4.jpg[/img]
注意:(上图166行)父process之所以会收到 {Down, _, _, _} 这类消息是因为父process monitor 子process; 当子process终止运行时,它变会发送该消息来告诉监控它的process
为了更加充分展示父process和子process是如何交互的,我自己画了一个图
[img]http://dl.iteye.com/upload/attachment/0079/8983/50151548-5b0a-3907-93e1-be657b2b11d0.jpg[/img]
配合上图,在我们看代码时就很容易看出,父process是如何和子process交互以及如何通过这些交互实现并发编译
那么rebar是什么呢?
如果你是Java程序员,那么你一定知道maven,maven可以用来构建java工程项目,并且提供jar包版本管理,编译,项目打包等一系列操作,而rebar就像maven一样,提供了对Erlang工程的构建,编译,依赖管理等操作(我相信随着Erlang的发展,rebar会成为标准被大家所接受)
关于rebar的下载安装以及使用,网上已经有很多例子,我也就不再赘述,那么我会说些什么呢?
1.rebar是如何执行编译的?
2.rebar执行流程是什么样的?
[color=red]--------------------------------------------------------------------------华丽分割线--------------------------------------------------------------------------[/color]
和编译相关的源文件主要有两个,它们分别是:[b]rebar_base_compiler.erl[/b] 和 [b]rebar_erlc_compiler.erl[/b],其中[b]最为核心的部分[/b]为:rebar_base_compile中的run/4方法,它包含了rebar编译的整个流程和策略
[img]http://dl.iteye.com/upload/attachment/0079/8971/41f8fd03-7c9b-388e-8995-659291b5a3dc.jpg[/img]
run方法有四个参数:
第一个参数Config表示rebar配置(关于如何初始化rebar配置以后会详说),在rebar配置中包含了编译选项(譬如是否含有debug_info);
第二个参数FirstFiles和第三个参数RestFiles都表示需要编译的Erlang源文件,但他们采用完全不同的编译策略(稍后会详述);
第四个参数CompileFn则是真正被用来编译源文件的方法
刚才我们说了,源文件分为两种:FirstFiles和RestFiles
其中对于FirstFiles采用[b]串行编译[/b],也就是说是它会按照FirstFiles中文件列出的顺序,逐个编译;
而对于RestFiles,则是[b]并发编译[/b],即会起多个子process去执行编译任务;
那么rebar为什么要这样分呢,我自己是这样理解的(一点拙见):
1.串行编译的好处是能够根据依赖关系控制源文件编译顺序,但缺点就是编译太慢,需要一个一个执行;
2.并行编译的好处就是效率高,但很显然它无法控制编译顺序;
鉴于此,rebar结合了两种编译方式,将源文件分为FirstFiles和RestFiles,然后对FirstFiles采用串行编译,对RestFiles执行并发编译(默认源文件都是并发编译(即RestFiles),需要串行编译的文件要在rebar.config文件中的erl_first_files属性中列出)
现在我们具体看看rebar串行编译的相关代码(compile_each方法)
[img]http://dl.iteye.com/upload/attachment/0079/8973/1e807d0a-9acb-306c-9d0e-e90d1485f618.jpg[/img]
这段代码比较好理解:递归编译源文件直到遍历完FirstFiles或者中间发生编译错误 (?FAIL 会抛出异常,然后中断当前操作),看完了串行编译,我们看下rebar的并行编译部分(它分为子process和父process两部分):
[b]a.子process部分(执行compile_worker方法)[/b]
[img]http://dl.iteye.com/upload/attachment/0079/8975/a5dd6856-c086-38a3-921a-6ac57d0ca051.jpg[/img]
[b]b.父process部分(执行compile_queue方法)[/b]
[img]http://dl.iteye.com/upload/attachment/0079/8977/23a5e27a-c0a9-3723-90b7-f562362756fd.jpg[/img]
[img]http://dl.iteye.com/upload/attachment/0079/8979/4bdb627d-252f-35e8-9589-0cf7219457b4.jpg[/img]
注意:(上图166行)父process之所以会收到 {Down, _, _, _} 这类消息是因为父process monitor 子process; 当子process终止运行时,它变会发送该消息来告诉监控它的process
为了更加充分展示父process和子process是如何交互的,我自己画了一个图
[img]http://dl.iteye.com/upload/attachment/0079/8983/50151548-5b0a-3907-93e1-be657b2b11d0.jpg[/img]
配合上图,在我们看代码时就很容易看出,父process是如何和子process交互以及如何通过这些交互实现并发编译