bufbuild/protocompile
GitHub: bufbuild/protocompile
一个用纯 Go 编写的 Protocol Buffers 解析与链接引擎,作为 protoc 的替代方案,驱动 Buf 工具链的底层编译器。
Stars: 344 | Forks: 35

# Protocompile
[](https://github.com/bufbuild/protocompile/actions/workflows/ci.yaml)
[](https://goreportcard.com/report/github.com/bufbuild/protocompile)
[](https://pkg.go.dev/github.com/bufbuild/protocompile)
此代码库包含一个用纯 Go 编写的 Protocol Buffers 解析/链接引擎。它可以作为
`protoc`(Google 官方的 Protocol Buffers 参考编译器)的替代方案。这就是驱动 [Buf](https://buf.build)
及其丰富工具集的编译器。
此代码库也是 [`github.com/jhump/protoreflect/desc/protoparse`](https://godoc.org/github.com/jhump/protoreflect/desc/protoparse)
包的精神继任者。如果你正在寻找能够原生支持较新 Protobuf 运行时 Go API
(`google.golang.org/protobuf`)的 `protoparse` 新版本,你找对地方了!
## Protocol Buffers
如果你偶然发现了这个代码库但不知道 Protocol Buffers 是什么,你可以去了解一下[官方
文档](https://developers.google.com/protocol-buffers)。Protocol Buffers,简称 Protobuf,是一种 IDL,用于
描述 API 和数据结构,同时也是一种用于高效传输和存储
数据的二进制编码格式。
如果你想了解更多关于该语言本身的信息(这正是此代码库所实现的),请查看 Buf 的
[Protobuf 指南](https://protobuf.com),其中包含了非常详细的语言规范。
### Descriptors
Descriptors 是用于描述 Protobuf 数据模式的“通用语言”。它们是运行时特性的基础,例如
反射和动态消息。它们也是 Protobuf 编译器的输出结果:编译器可以生成它们并将其
写入文件(文件内容是 [`FileDescriptorSet`](https://github.com/protocolbuffers/protobuf/blob/v21.7/src/google/protobuf/descriptor.proto#L55-L59) 的二进制编码形式)
或者将它们发送到 [plugin](https://docs.buf.build/reference/images#plugins) 以便为特定的
编程语言生成代码。
Descriptors 类似于语法树中的节点:文件 descriptor 的内容与生成它的
源文件中的元素密切相关。此外,descriptor 模型的数据结构本身也是用
[Protobuf](https://github.com/protocolbuffers/protobuf/blob/v21.7/src/google/protobuf/descriptor.proto) 定义的。
## 使用此代码库
此代码库的主要 API 位于根包中:`github.com/bufbuild/protocompile`。这是建议的入口
点,提供了一个名为 `Compiler` 的类型,用于将 Protobuf 源文件编译成 descriptors。此外还有
许多子包,其中大部分实现了编译器的各个阶段。以下是概览(_不_按字母顺序
排列):
* [`protocompile`](https://pkg.go.dev/github.com/bufbuild/protocompile):
这是入口点,用于配置和启动编译操作。
* [`parser`](https://pkg.go.dev/github.com/bufbuild/protocompile/parser):
这是编译器的第一阶段。它解析 Protobuf 源代码并生成 AST。此包还可以
从 AST 生成文件 descriptor proto。
* [`ast`](https://pkg.go.dev/github.com/bufbuild/protocompile/ast):
此包为 Protobuf 语言建模了一个抽象语法树 (AST)。
* [`linker`](https://pkg.go.dev/github.com/bufbuild/protocompile/linker):
这是编译器的第二阶段。descriptor proto(由 AST 生成)被链接,产生比简单的 descriptor protos 更
有用的数据结构。此步骤还对源代码执行多项验证,
例如确保所有类型引用都是正确的,并且源代码不会尝试定义两个同名的
元素。
* [`options`](https://pkg.go.dev/github.com/bufbuild/protocompile/options):
这是编译器的下一个阶段:解释选项。来自上一
阶段的链接数据结构用于验证和解释所有选项。
* [`sourceinfo`](https://pkg.go.dev/github.com/bufbuild/protocompile/sourceinfo):
这是编译器的最后阶段:生成源代码信息。源代码信息包含将 descriptor 中的
元素映射到其原始源文件中所在位置的元数据。这包括对
注释的访问。为了提供正确的选项源信息,它必须在最后执行,即在选项被
解释之后。
* [`reporter`](https://pkg.go.dev/github.com/bufbuild/protocompile/reporter):此包提供了编译器生成的错误类型
以及编译器用来向调用代码报告错误和警告的接口。
* [`walk`](https://pkg.go.dev/github.com/bufbuild/protocompile/walk):
此包提供了用于遍历 descriptor(或 descriptor proto)
层级结构中所有元素的函数。
* [`protoutil`](https://pkg.go.dev/github.com/bufbuild/protocompile/protoutil):
此包包含一些用于与 Protobuf descriptors 交互的其他实用函数。
### 从 `protoparse` 迁移
此代码库与其前身 `github.com/jhump/protoreflect/desc/protoparse` 之间存在一些差异。
* 如果你想包含“标准导入”(即 `protoc` 附带的知名文件),你必须
显式地进行操作。为此,请使用 `protocompile.WithStandardImports` 包装你的 resolver。
* 如果你使用过 `protoparse.FileContentsFromMap`,在这个新代码库中,你将使用 `protocompile.SourceResolver`,然后
将 `protocompile.SourceAccessorFromMap` 用作其 accessor 函数。
* 如果你使用过 `Parser.ParseToAST`,你将不再使用 `protocompile` 包,而是直接使用此代码库 `parser` 子包中的 `parser.Parse`。这会返回
给定文件内容的 AST。
* 如果你使用过 `Parser.ParseFilesButDoNotLink`,在此代码库中仍然可行,但不能直接通过
单个函数提供。相反,你需要执行以下几个步骤:
1. 使用 `parser.Parse` 解析源代码。然后使用 `parser.ResultFromAST` 构建一个包含文件
descriptor proto 的结果。
2. 使用 `options.InterpretUnlinkedOptions` 解释无需链接即可解释的任何选项。这可能会
在 descriptor proto 中留下一些未解释的选项(包括所有自定义选项)。
3. 如果你需要该文件的源代码信息,最后使用上一步返回的索引调用 `sourceinfo.GenerateSourceInfo`,
并将其存储在文件 descriptor proto 中。
标签:EVTX分析, 日志审计