plz初窥门径
因为工作的原因,在前司时,我就对bazel产生了深厚的兴趣,奈何各种原因没有在工作落地,甚至来不及在团队内普及monorepo的概念,但一直记挂于心,也应了那句话:念念不忘,必有回响。
bazel到底是什么呢?
Bazel 是一个支持多语言构建的构建系统
我为何对bazel如此上心呢,根据官网的宣传,主要有两点:
仅重新构建必要的代码。使用 Bazel' 先进的本地和分布式缓存、优化的依赖项分析和并行执行功能,实现快速增量构建。
快速构建,一直是我非常在意的一个特性,还有一点就是跨语言、跨平台
使用 Java、C++、Go、Android、iOS 以及其他许多语言和平台进行构建和测试。Bazel 在 Windows、macOS 和 Linux 上运行。
这一点,跨语言这一点我也是后来才领悟到的,毕竟如果你经常跨编程语言开发,学会一套bazel的构建规则即可,这一点还真是挺妙的。
不过接下来我要聊的是please, 跟bazel可以说非常类似,不同的是,这个please是使用go开发的,因为我的主力编程语言是go,偶然发现了这please,觉得还挺有趣,就用它来做示例吧。
我的示例来源于please官网的Getting started with Go,我们先来看一下plz-demo的目标结构
├── .plzconfig
├── pleasew
├── src
│ ├── BUILD
│ ├── greetings
│ │ ├── BUILD
│ │ ├── greetings.go
│ │ └── greetings_test.go
│ └── main.go
└── third_party
└── go
└── BUILD
是的,你没看错,没有go.mod
,当我运行plz run //src:main
,plz会根据BUILD的配置完成依赖分析、下载、缓存,有一说一,速度还是挺快的。
我用常规方式下go-demo的代码目标结构
├── go.mod
├── go.sum
├── greetings
│ ├── greetings.go
│ └── greetings_test.go
└── main.go
直观来看,go.mod这类方式肯定最简单,最舒服,跟go的生态适配性也更好,一个可能不太恰当的比方:go.mod之于plz/blazel,好比gc与自己管理依赖的区别。
话不多说,我们先来看下plz-demo/src/BUILD长啥样
go_binary(
name = "main",
srcs = ["main.go"],
deps = ["//src/greetings:greetings"],
)
还是很容易看懂的,最终生成的
二进制name: 在plz-out/bin/src路径下
-main文件
第三方依赖
再来看third_parth/go下的BUILD(third_parth文件夹名字只是一个约定,不强制),不理解第一行PUBLIC
的意义所在?
package(default_visibility = ["PUBLIC"])
go_module(
name = "assert",
module = "github.com/go-playground/assert",
version = "v1.2.1",
)
也挺清晰的,声明了第三依赖github.com/go-playground/assert
的,功能上与go.mod类似,事实上assert这个第三方依赖是在greetings_test.go
中使用到的。第一次跑plz test //src/...
//src/greetings:greetings_test 1 test run in 0s; 1 passed [cached]
1 test target and 1 test run; 1 passed.
Total time: 260ms real, 0s compute.
第二次
//src/greetings:greetings_test 1 test run in 0s; 1 passed [cached]
1 test target and 1 test run; 1 passed.
Total time: 70ms real, 0s compute.
缓存果然很强大
对比go-demo跑test:
❯ go test -v ./...
? example_module [no test files]
=== RUN TestGreeting
--- PASS: TestGreeting (0.00s)
PASS
ok example_module/greetings 0.212s
嗯,可见差别并不明显
再来看src/greetings/BUILD
go_library(
name = "greetings",
srcs = ["greetings.go"],
visibility = ["//src/..."],
)
go_test(
name = "greetings_test",
srcs = ["greetings_test.go"],
deps = [
":greetings",
"//third_party/go:assert",
],
external = True,
)
虽然写的挺多,但还是容易理解的,不太明白这里external = True
为何意,一般而言,test代码其它地方也用不到。
最后还看一下根目录下的.plzconfig
; Please config file
; Leaving this file as is is enough to use plz to build your project.
; Please will stay on whatever version you currently have until you run
; 'plz update', when it will download the latest available version.
;
; Or you can uncomment the following to pin everyone to a particular version;
; when you change it all users will automatically get updated.
; [please]
; version = 16.28.0
[go]
;gotool = ...
;goroot - ...
importpath = example_module
[build]
;path = $(dirname $(which go)):/usr/local/bin:/usr/bin:/bin
path =/Users/yourname/.gvm/gos/go1.17/bin:/usr/local/bin:/usr/bin:/bin
需要配置下go的工具链,让我比较疑惑的是plz似乎并不能识别环境变量,至少在我测试的过程中是这样的。
总结下来,plz还是挺不错的,使用门槛也不高,只是对于常规业务小型项目,与go mod对比起来,无任何优势,这么说也不太公平,毕竟plz/bazel也有自己的优势与适用场景。目前我就看到国内TiDB有在项目中用到了bazel,听说效果不错。这一篇算是真正意义上入坑,毕竟只是小小demo了一把,期待以后能在合适的工作场景中用到,这正是探索新技术的乐趣所在,just for fun!