`go mod tidy` 抱怨缺少由 Bazel 生成的 protobuf 包。

huangapple go评论117阅读模式
英文:

`go mod tidy` complains that the bazel-generated protobuf package is missing

问题

我有一个位于目录中的.proto protobuf定义文件,并且我正在使用Bazel构建一个go库(使用gazelle生成下面的BUILD.bazel文件):

load("@rules_proto//proto:defs.bzl", "proto_library")
load("@io_bazel_rules_go//go:def.bzl", "go_library")
load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")

proto_library(
    name = "events_proto",
    srcs = ["events.proto"],
    visibility = ["//visibility:public"],
    deps = ["@com_google_protobuf//:timestamp_proto"],
)

go_proto_library(
    name = "proto_go_proto",
    importpath = "github.com/acme/icoyote/proto",
    proto = ":events_proto",
    visibility = ["//visibility:public"],
)

go_library(
    name = "proto",
    embed = [":proto_go_proto"],
    importpath = "github.com/acme/icoyote/proto",
    visibility = ["//visibility:public"],
)

一些其他代码依赖于//icoyote/proto:proto,当我在我的模块中运行go mod tidy时,它抱怨找不到包github.com/acme/icoyote/proto

go: finding module for package github.com/acme/icoyote/proto
github.com/acme/icoyote/cmd/icoyote imports
        github.com/acme/icoyote/proto: no matching versions for query "latest"

任何没有Bazel集成的IDE(例如VSCode、GoLand/IntelliJ没有Bazel插件的情况下)也会抱怨。

我该怎么办?

英文:

I have a .proto protobuf definition file in a dir and I'm building a go library from it with Bazel like so (BUILD.bazel file below generated using gazelle):

load("@rules_proto//proto:defs.bzl", "proto_library")
load("@io_bazel_rules_go//go:def.bzl", "go_library")
load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")

proto_library(
    name = "events_proto",
    srcs = ["events.proto"],
    visibility = ["//visibility:public"],
    deps = ["@com_google_protobuf//:timestamp_proto"],
)

go_proto_library(
    name = "proto_go_proto",
    importpath = "github.com/acme/icoyote/proto",
    proto = ":events_proto",
    visibility = ["//visibility:public"],
)

go_library(
    name = "proto",
    embed = [":proto_go_proto"],
    importpath = "github.com/acme/icoyote/proto",
    visibility = ["//visibility:public"],
)

Some other code depends on //icoyote/proto:proto, and when I run go mod tidy in my module, it complains that it can't find the package github.com/acme/icoyote/proto:

go: finding module for package github.com/acme/icoyote/proto
github.com/acme/icoyote/cmd/icoyote imports
        github.com/acme/icoyote/proto: no matching versions for query "latest"

Any IDE that doesn't have Bazel integration (e.g. VSCode, GoLand/IntelliJ without the Bazel plugin) complains as well

What do I do?

答案1

得分: 3

这是因为Bazel在BUILD文件中的go_proto_library规则中使用protoc生成.go文件,但只将它们写入bazel-bin下的临时目录供go_library规则使用,而go mod tidy似乎不会查看bazel-bin(可能是因为它是一个符号链接,而且即使它查看了,相对于go.mod位置的这些文件的路径也是错误的)。

一种选择是通过自己调用protoc手动生成go文件,并在BUILD文件中删除proto_librarygo_proto_library规则,然后将go_library规则更改为构建生成的文件。这种方法不太理想,因为每次更改.proto文件时都必须手动重新运行protoc(如果将其放入//go:generate指令中,则必须重新运行go generate)。

相反,我们可以采取以下步骤:

1)在包含.proto文件的目录中添加一个名为empty.go的文件,内容如下:

package proto

2)然后告诉gazelle忽略empty.go(这样在运行gazelle --fix时它就不会尝试向BUILD文件中添加go_library规则)。我们可以通过在BUILD文件中添加以下内容来实现:

# gazelle:exclude empty.go

这样就足够让go mod tidy保持安静了。

这也会使IDE停止对导入的警告,尽管当引用应该在该包中的任何内容时,仍会出现错误。如果您不想放弃您的IDE,而是使用带有Bazel插件的优秀GoLand或IntelliJ IDEA,您可能需要采用手动的protoc方法。也许有一种方法可以创建一个符号链接,指向Bazel在bazel-bin下写出生成的.go文件的位置,并强制go mod tidy跟随它,但我还没有尝试过。如果您尝试并且成功了,请分享一下!

英文:

This is happening of course because because Bazel does generate .go files using protoc under the covers for the go_proto_library rule in the BUILD file, but only writes them out to a temp dir under bazel-bin to be used by the go_library rule, and go mod tidy doesn't seem look into bazel-bin (probably because it's a symlink but also if it did, the path of those files relative to the location of go.mod is all wrong)

One option is to manually generate the go files by calling protoc on your own, and remove the proto_library and go_proto_library rules in the BUILD file, then change the go_library rule to build your generated files. This is suboptimal because you have to manually rerun protoc every time you make changes to the .proto file (and if you put it into a //go:generate directive, you have to rerun go generate).

Instead, we can do the following:

  1. Add a file empty.go to the dir that contains the .proto file. It should look like this:
package proto
  1. Then tell gazelle to ignore empty.go (so it doesn't try to add a go_library rule to the BUILD file when you run gazelle --fix). We do that by adding the following to the BUILD file:
# gazelle:exclude empty.go

That's enough to make go mod tidy shut up.

This will also make the IDE stop complaining about the import, although you'll still get errors when referring to anything that's supposed to be in that package. If you don't want to abandon your IDE for an excellent GoLand or IntelliJ IDEA with a Bazel plugin, you might have to resort to the manual protoc method. Perhaps there's a way to create a symlink to wherever Bazel writes out the generated .go files under bazel-bin and force go mod tidy to follow it, but I haven't tried that. If you do and it works, do share!

huangapple
  • 本文由 发表于 2023年2月14日 07:34:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/75442156.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定