英文:
Import cycle in tensorflow protobufs
问题
我正在尝试编写客户端代码与一个TensorFlow服务器进行通信。我需要tensorflow
和tensorflow_serving
的Golang编译的protobuf文件。这些文件不容易获取,但我通过这个链接成功获取到了。基本上,我使用buf来生成它们。这是buf的yaml配置文件:
version: v1
managed:
enabled: true
optimize_for: CODE_SIZE
# Go
go_package_prefix:
default: "some/path"
plugins:
- plugin: buf.build/protocolbuffers/go
out: gen/proto/go
这个命令成功运行了,但是应用程序的日志显示:
package command-line-arguments
imports my-package/internal/infer
imports my-package/internal/infer/tensorflow_serving/apis
imports my-package/internal/infer/tensorflow/core/protobuf
imports my-package/internal/infer/tensorflow/compiler/xla/stream_executor
imports my-package/internal/infer/tensorflow/compiler/xla
imports my-package/internal/infer/tensorflow/compiler/xla/service
imports my-package/internal/infer/tensorflow/compiler/xla: import cycle not allowed
请注意,tensorflow
和tensorflow_serving
下的所有内容都是直接从原始存储库编译的。
对我来说,像TensorFlow这样广泛使用的库竟然会出现循环导入是令人惊讶的,但也许确实存在这个问题。我该如何解决这个问题呢?
英文:
I am trying to write client code to talk to a tensorflow server. I need the golang compiled protobufs for tensorflow
and tensorflow_serving
. These are not easy to come by, I managed to do so through this. Basically, using buf to generate them. Here is the buf yaml:
version: v1
managed:
enabled: true
optimize_for: CODE_SIZE
# Go
go_package_prefix:
default: "some/path"
plugins:
- plugin: buf.build/protocolbuffers/go
out: gen/proto/go
This runs successfully, but running the application logs:
package command-line-arguments
imports my-package/internal/infer
imports my-package/internal/infer/tensorflow_serving/apis
imports my-package/internal/infer/tensorflow/core/protobuf
imports my-package/internal/infer/tensorflow/compiler/xla/stream_executor
imports my-package/internal/infer/tensorflow/compiler/xla
imports my-package/internal/infer/tensorflow/compiler/xla/service
imports my-package/internal/infer/tensorflow/compiler/xla: import cycle not allowed
Note that everything under tensorflow
and tensorflow_serving
is directly compiled from the original repositories.
It is surprising to me that something as widely used as tensorflow should have an import cycle, but maybe it does. How can I resolve this?
答案1
得分: 1
TL;DR
根本原因是https://github.com/tensorflow/tensorflow仓库没有正确组织proto文件(或者至少对Go不友好)。
以下两个文件在Go中导致了循环导入(xla
->xla/service
->xla
):
-
tensorflow/compiler/xla/xla.proto
import "tensorflow/compiler/xla/service/hlo.proto"
-
tensorflow/compiler/xla/service/hlo.proto
import "tensorflow/compiler/xla/xla_data.proto"
由于xla_data.proto
没有导入其他文件,我们可以将其移动到自己的包中以打破循环导入。我们可以利用buf的覆盖功能来实现。这是最终的buf.gen.yaml
文件:
version: v1
managed:
enabled: true
go_package_prefix:
default: example.com/mymodule/internal
override:
GO_PACKAGE:
# move the generated xla_data.pb.go file into package xla/data to break the import cycle.
tensorflow/compiler/xla/xla_data.proto: 'example.com/mymodule/internal/tensorflow/compiler/xla/data'
plugins:
- name: go
out: internal
opt:
- module=example.com/mymodule/internal
- name: go-grpc
out: internal
opt:
- module=example.com/mymodule/internal
使用buf编译Tensorflow proto文件的完整设置
以下是最终的目录结构:
├── buf.gen.yaml
├── buf.work.yaml
├── buf.yaml
├── go.mod
├── go.sum
├── internal
│ ├── tensorflow
│ └── tensorflow_serving
└── testdata
├── serving
└── tensorflow
buf.gen.yaml:参见"TL;DR"部分。
buf.work.yaml:
version: v1
directories:
- testdata/serving
- testdata/tensorflow
buf.yaml:
version: v1
breaking:
use:
- FILE
lint:
use:
- DEFAULT
这是我的环境:
$ go version
go version go1.20.3 linux/amd64
$ buf --version
1.17.0
$ protoc --version
libprotoc 3.12.4
$ protoc-gen-go --version
protoc-gen-go v1.30.0
$ protoc-gen-go-grpc --version
protoc-gen-go-grpc 1.3.0
$ git version
git version 2.37.2
现在在此目录的根目录中执行以下命令:
$ go mod init example.com/mymodule
$ go get google.golang.org/grpc
$ git clone https://github.com/tensorflow/tensorflow.git testdata/tensorflow
$ git clone https://github.com/tensorflow/serving.git testdata/serving
$ buf generate
$ go build ./...
注意:
- TensorFlow仓库被克隆到
testdata
目录中,以便go build
会忽略它们。 - 设置将文件生成到
internal
目录中。您可以修改buf.gen.yaml
文件以将它们放置在任何您想要的位置。 go build ./...
不会报告任何错误。但我不确定生成的文件是否有效。
英文:
TL;DR
The root cause is that the repositry https://github.com/tensorflow/tensorflow does not organize the proto files correctly (or at least does not make it friendly for Go).
The following two files lead to the import cycle (xla
->xla/service
->xla
) in Go:
-
tensorflow/compiler/xla/xla.proto
import "tensorflow/compiler/xla/service/hlo.proto"
-
tensorflow/compiler/xla/service/hlo.proto
import "tensorflow/compiler/xla/xla_data.proto"
Since xla_data.proto
does not import any other files, we can move it into its own package to break the import cycle. We can utilize the override feature of buf to do this. Here is the final buf.gen.yaml
file:
version: v1
managed:
enabled: true
go_package_prefix:
default: example.com/mymodule/internal
override:
GO_PACKAGE:
# move the generated xla_data.pb.go file into package xla/data to break the import cycle.
tensorflow/compiler/xla/xla_data.proto: 'example.com/mymodule/internal/tensorflow/compiler/xla/data'
plugins:
- name: go
out: internal
opt:
- module=example.com/mymodule/internal
- name: go-grpc
out: internal
opt:
- module=example.com/mymodule/internal
The Full Setup to Compile Tensorflow proto Files with buf
Here is the final directory structure:
├── buf.gen.yaml
├── buf.work.yaml
├── buf.yaml
├── go.mod
├── go.sum
├── internal
│   ├── tensorflow
│   └── tensorflow_serving
└── testdata
├── serving
└── tensorflow
buf.gen.yaml: see the "TL;DR" section.
buf.work.yaml:
version: v1
directories:
- testdata/serving
- testdata/tensorflow
buf.yaml:
version: v1
breaking:
use:
- FILE
lint:
use:
- DEFAULT
Here is my environment:
$ go version
go version go1.20.3 linux/amd64
$ buf --version
1.17.0
$ protoc --version
libprotoc 3.12.4
$ protoc-gen-go --version
protoc-gen-go v1.30.0
$ protoc-gen-go-grpc --version
protoc-gen-go-grpc 1.3.0
$ git version
git version 2.37.2
Now execute the following commands in the root of this directory:
$ go mod init example.com/mymodule
$ go get google.golang.org/grpc
$ git clone https://github.com/tensorflow/tensorflow.git testdata/tensorflow
$ git clone https://github.com/tensorflow/serving.git testdata/serving
$ buf generate
$ go build ./...
Notes:
- The tensorflow repositories are cloned into the
testdata
directory so thatgo build
will ignore them. - The setup generates the files into the
internal
directory. You can modify thebuf.gen.yaml
file to place them anywhere you want. go build ./...
does not report any error. But I'm not sure whether the generated files are valid or not.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论