PowerProto: gRPC工具链(protoc, protoc-gen-go)的一键安装与版本控制

中文 | English

PowerProto主要用于解决下面三个问题:

  1. 降低gRPC的使用门槛与使用成本。
  2. 解决protoc以及其相关插件(比如protoc-gen-go、protoc-gen-grpc-gateway)的版本控制问题。
  3. 高效管理proto的编译,实现多平台兼容、一键安装与编译。

功能

  1. 实现protoc的一键安装与多版本管理。
  2. 实现protoc相关插件(比如protoc-gen-go)的一键安装与多版本管理。
  3. 通过配置文件管理proto的编译,而非shell脚本,提高可读性与兼容性。
  4. 引导式生成配置文件,跨平台兼容,一份配置在多个平台均可以实现一键编译。
  5. 支持批量、递归编译proto文件,提高效率。
  6. 跨平台支持PostAction,可以在编译完成之后执行一些常规操作(比如替换掉所有生成文件中的"omitempty")。
  7. 支持PostShell,在编译完成之后执行特定的shell脚本。
  8. 支持 google api, gogo protobuf 等的一键安装与版本控制。

安装与依赖

PowerProtogogitprotocPowerProtoprotocHTTP_PROXYHTTPS_PROXYprotocgithub.comgit ls-remotegitgoGOPROXY用户目录/.powerprotoPOWERPROTO_HOMEpowerprotoaliaspp

一、通过Go进行安装

直接执行下面的命令即可进行安装:

go install github.com/storyicon/powerproto/cmd/powerproto@latest

二、开箱即用版本

Github Release Page

命令介绍

你可以通过 powerproto -h 来查看帮助,比如:

powerproto -h
powerproto init -h
powerproto tidy -h
powerproto build -h
powerproto env -h

它的好处是命令行中的文档永远和你的二进制版本保持一致。而Github上的文档可能会一直是对应最新的二进制。

一、初始化配置

可以通过下面的命令进行配置的初始化:

powerproto init

二、整理配置

可以通过下面的命令整理配置:

powerproto tidy
powerproto.yaml

你也可以指定整理哪个配置文件:

powerproto tidy [the path of proto file]

整理配置主要包含两个操作:

  1. 通过查询,将版本中的latest替换为真实的最新版本号。
  2. 安装配置文件中定义的所有依赖。
-ddebug模式

三、编译Proto文件

可以通过下面的命令进行Proto文件的编译:

// 编译指定的proto文件
powerproto build xxxx.proto // 编译当前目录下的所有proto文件
powerproto build . // 递归编译当前目录下的所有proto文件,包括子文件夹。
powerproto build -r .
powerproto.yaml
scopepluginsprotocoptionsimportPaths-pPostActionPostShell
protocproto文件protocWorkDir
-ddebug模式-ydryRun模式

四、查看环境变量

如果你的命令一直卡在某个状态,大概率是出现网络问题了。

你可以通过下面的命令来查看环境变量是否配置成功:

powerproto env

示例

/mnt/data/hello
$ pwd
/mnt/data/hello $ tree
./apis
└── hello.proto
powerproto.yaml
powerproto.yamlpowerproto init
scopes:
- ./
protoc: latest
protocWorkDir: ""
plugins:
protoc-gen-go: google.golang.org/protobuf/cmd/protoc-gen-go@latest
protoc-gen-go-grpc: google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
repositories:
GOOGLE_APIS: https://github.com/googleapis/googleapis@75e9812478607db997376ccea247dd6928f70f45
options:
- --go_out=.
- --go_opt=paths=source_relative
- --go-grpc_out=.
- --go-grpc_opt=paths=source_relative
importPaths:
- .
- $GOPATH
- $POWERPROTO_INCLUDE
- $GOOGLE_APIS/github.com/googleapis/googleapis
postActions: []
postShell: ""

在任意目录执行:

powerproto build -r /mnt/data/hello/apis

你都可以得到编译后的文件

$ pwd
/mnt/data/hello $ tree
./apis
├── hello.pb.go
├── hello.proto
└── hello_grpc.pb.go
powerproto.yaml
powerproto.yaml
$POWERPROTO_HOME/protoc/3.17.3/protoc --go_out=. \
--go_opt=paths=source_relative \
--go-grpc_out=. \
--go-grpc_opt=paths=source_relative \
--proto_path=/mnt/data/hello \
--proto_path=$GOPATH \
--proto_path=$POWERPROTO_HOME/include \
--proto_path=$POWERPROTO_HOME/gits/75e9812478607db997376ccea247dd6928f70f45/github.com/googleapis/googleapis \
--plugin=protoc-gen-go=$POWERPROTO_HOME/plugins/google.golang.org/protobuf/cmd/protoc-gen-go@v1.27.1/protoc-gen-go \
--plugin=protoc-gen-go-grpc=$POWERPROTO_HOME/plugins/google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1.0/protoc-gen-go-grpc
/mnt/data/hello/apis/hello.proto

更多的例子可以参考 示例.

配置文件

配置文件用于描述编译proto文件时,各种依赖的版本以及参数等。

powerproto init

解释

以下面这份配置文件为例:

# 必填,scopes 用于定义作用域,即当前配置项对项目中的哪些目录生效
scopes:
- ./
# 必填,protoc的版本,可以填 latest,会自动转换成最新的版本
protoc: 3.17.3
# 选填,执行protoc命令的工作目录,默认是配置文件所在目录
# 支持路径中混用环境变量,比如$GOPATH
protocWorkDir: ""
# 选填,定义依赖的Git存储库
# 一般用于公共的protobuf库的依赖控制
repositories:
# 定义依赖 27156597fdf4fb77004434d4409154a230dc9a32 版本的 https://github.com/googleapis/googleapis
# 并且定义其名字为 GOOGLE_APIS
# 在 importPaths 中可以通过 $GOOGLE_APIS 来引用它
GOOGLE_APIS: https://github.com/googleapis/googleapis@27156597fdf4fb77004434d4409154a230dc9a32
# 定义依赖 226206f39bd7276e88ec684ea0028c18ec2c91ae 版本的 https://github.com/gogo/protobuf
# 并且定义其名字为 GOGO_PROTOBUF
# 在 importPaths 中可以通过 $GOGO_PROTOBUF 来引用它
GOGO_PROTOBUF: https://github.com/gogo/protobuf@226206f39bd7276e88ec684ea0028c18ec2c91ae
# 必填,代表scope匹配的目录中的proto文件,在编译时需要用到哪些插件
plugins:
# 插件的名字、路径以及版本号。
# 插件的地址必须是 path@version 的格式,version可以填latest,会自动转换成最新的版本。
protoc-gen-deepcopy: istio.io/tools/cmd/protoc-gen-deepcopy@latest
protoc-gen-go: google.golang.org/protobuf/cmd/protoc-gen-go@latest
protoc-gen-go-json: github.com/mitchellh/protoc-gen-go-json@v1.0.0
protoc-gen-grpc-gateway: github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@v2.5.0
# 必填,定义了编译proto文件时 protoc 的参数
options:
- --go_out=paths=source_relative:.
- --go-json_out=.
- --deepcopy_out=source_relative:.
- --grpc-gateway_out=.
- --go-grpc_out=paths=source_relative:.
# 必填,定义了构建时 protoc 的引用路径,会被转换为 --proto_path (-I) 参数。
importPaths:
# 特殊变量。代表当前配置文件所在文件夹
- .
# 环境变量。可以使用环境变量
# 也支持 $GOPATH/include 这样的混合写法
- $GOPATH
- $POWERPROTO_INCLUDE
# 特殊变量。引用待编译的proto文件所在的目录
# 比如将要编译 /a/b/data.proto,那么 /a/b 目录将会被自动引用
- $SOURCE_RELATIVE
# 引用 repositories 中的 GOOGLE_APIS
- $GOOGLE_APIS/github.com/googleapis/googleapis
# 引用 repositories 中的 GOGO_PROTOBUF
- $GOGO_PROTOBUF
# 选填,构建完成之后执行的操作,工作目录是配置文件所在目录
# postActions是跨平台兼容的
# 注意,必须在 powerproto build 时附加 -p 参数,才会执行配置文件中的postActions
postActions: []
# 选填,构建完成之后执行的shell脚本,工作目录是配置文件所在目录
# postShell不是跨平台兼容的。
# 注意,必须在 powerproto build 时附加 -p 参数,才会执行配置文件中的postShell
postShell: |
// do something

匹配模式与工作目录

powerproto.yaml

多配置组合

一个配置文件中支持填写多份配置,多份配置之间以 "---" 进行分割。

在下面的示例中,apis1目录使用的是v1.25.0的protoc-gen-go,而apis2目录使用的则是v1.27.0的protoc-gen-go。

scopes:
- ./apis1
protoc: v3.17.3
protocWorkDir: ""
plugins:
protoc-gen-go: google.golang.org/protobuf/cmd/protoc-gen-go@v1.25.0
protoc-gen-go-grpc: google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1.0
repositories:
GOOGLE_APIS: https://github.com/googleapis/googleapis@75e9812478607db997376ccea247dd6928f70f45
options:
- --go_out=.
- --go_opt=paths=source_relative
- --go-grpc_out=.
- --go-grpc_opt=paths=source_relative
importPaths:
- .
- $GOPATH
- $POWERPROTO_INCLUDE
- $GOOGLE_APIS/github.com/googleapis/googleapis
postActions: []
postShell: "" --- scopes:
- ./apis2
protoc: v3.17.3
protocWorkDir: ""
plugins:
protoc-gen-go: google.golang.org/protobuf/cmd/protoc-gen-go@v1.27.0
protoc-gen-go-grpc: google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.1.0
repositories:
GOOGLE_APIS: https://github.com/googleapis/googleapis@75e9812478607db997376ccea247dd6928f70f45
options:
- --go_out=.
- --go_opt=paths=source_relative
- --go-grpc_out=.
- --go-grpc_opt=paths=source_relative
importPaths:
- .
- $GOPATH
- $POWERPROTO_INCLUDE
- $GOOGLE_APIS/github.com/googleapis/googleapis
postActions: []
postShell: ""

PostAction

PostShell
powerproto build-pPostActionPostShell

目前,PostAction支持下面这些命令:

命令 描述 函数原型
copy 复制文件或文件夹 copy(src string, dest string) error
move 移动文件或文件夹 move(src string, dest string) error
remove 删除文件或文件夹 remove(path ...string) error
replace 批量替换文件中的字符串 replace(pattern string, from string, to string) error

1. copy

用于复制文件或文件夹,其函数原型为:

copy(src string, dest string) error

为了安全以及配置的兼容性,参数中只允许填写相对路径。

如果目标文件夹已经存在,将会合并。

下面的例子将会把配置文件所在目录下的a复制到b:

postActions:
- name: copy
args:
- ./a
- ./b

2. move

用于移动文件或文件夹,其函数原型为:

move(src string, dest string) error

为了安全以及配置的兼容性,参数中只允许填写相对路径。

如果目标文件夹已经存在,将会合并。

下面的例子将会把配置文件所在目录下的a移动到b:

postActions:
- name: move
args:
- ./a
- ./b

3. remove

用于删除文件或文件夹,其函数原型为:

remove(path ...string) error

为了安全以及配置的兼容性,参数中只允许填写相对路径。

下面的例子将会删除配置文件所在目录下的a、b、c:

postActions:
- name: remove
args:
- ./a
- ./b
- ./c

4. replace

用于批量替换文件中的字符串,其函数原型为:

replace(pattern string, from string, to string) error

其中:

  • pattern是支持通配符的相对路径。
  • from是要被替换的字符串。
  • to是替换为的字符串。
,omitempty
postActions:
- name: replace
args:
- ./apis/**/*.go
- ',omitempty'
- ""