八卦一下Starlark语言
八卦一下Starlark语言
编译移植TensorFlow时用到Bazel这一构建工具,Bazel用Starlark语法来编写WORKSPACE/BUILD文件,它们是类似于Make中的makeifle、CMake中的CMakeLists的存在。
来源:https://blog.bazel.build/2017/03/21/design-of-skylark.html
Starlark语言简史
早些年google用make+makefile构建代码,后来代码多了,发现make不适合(反正我是觉得makefile语法太怪异了,之前看ucore/JOS操作系统内核时候就很慌)。
一个临时办法是手写一个描述文件BUILD
,然后用Python生成makefile文件(沿着这种思路,考虑VC/gcc/XCode等多种平台,就是cmake了)。
但是其实Make更大问题是速度太慢,于是google搞了个Blaze,开源版本叫Bazel(比如TensorFlow默认就用Bazel构建)。
Blaze2006年一路过来,也是各种经验啊:用BUILD
替代Makefile
,用Blaze
替代Make
,那么似乎应该让Blaze
来解析BUILD
然后调编译器连接器干活,因为Make
就是先听Makefile哔哔然后向gcc和ar发号施令的。
但是既然已经是重新实现一个构建系统了,能不能把描述文件的语法搞的human friendly一点啊?干脆用Python写算了吧!
诶,如果BUILD
用纯Python写,那Blaze
就不需要解析BUILD
了。但是!纯Python写/解析BUILD
,太特么自由了,A君写一个宏,B君又写一个宏,实现同样功能。天啊,google那么多项目,这么搞搞死人啊。
好吧,捋一捋:
- 构建的描述文件,语法得简单,或者说大家基本上熟悉的,门槛低点
- 构建描述文件中常用的什么目标啊、库啊、路径啊、依赖啊,得有统一的版本
- 构建速度得快点
其中对于前面两点,干脆搞个阉割版的Python(语言)吧!搞一些限定,但是python的常用基本语法给他留着。
好了,这就是Starlark了。对,它改过名,以前叫Skylark。
Starlark设计需求
Starlark除了是一门Python方言,它更是Blaze(Bazel)的前端。要想Bazel构建速度快,应该避免重复计算,Starlark作为预处理器,这么干的:
- 搞了一个依赖图(graph of dependencies),这么一来不管你在
BUILD
和.bzl
文件中怎么瞎import
,import
的顺序不会影响构建速度 - 根据这个图呢,先算“叶子节点”,也就是不依赖任何东西的任务,然后把依赖叶子节点的任务做做掉。好吧,这就是图的搜索算法,主要标记visit flag来避免重复计算。
- 每个文件只被加载一次:缓存着,避免I/O阻塞计算速度
- 考虑到多个BUILD文件中可能使用了同一个变量,多线程解析各个BUILD文件时给变量加只读锁