我试图让protoc
将生成的文件输出到我所有.proto
文件所在的文件夹中的一个文件夹。首先,我希望我们都能同意,这些命令令人困惑,而且不是很直观。我偶然发现了这个documentation,它似乎可以解释一切,但事情并不起作用。所以我的protobuf
文件在一个名为proto的文件夹中。我有几个protobuf
文件,导入另一个protobuf
文件。我这样导入它们:
package proto;
option go_package = "github.com/me/golang-grpc-server/proto";
import "proto/another_proto.proto";
message Proto1 {
...
...
repeated proto.AnotherProto another_proto = 6;
}
应该可以吧protoc
不知道该怎么办。如果我运行这个命令。
protoc --proto_path=proto --go_out=out --go_opt=paths=source_relative --go-grpc_out=out --go-grpc_opt=paths=source_relative proto1.proto another_proto.proto
protoc
会给予以下错误:
proto/another_proto.proto: File not found.
proto1.proto:7:1: Import "proto/another_proto.proto" was not found or had errors.
proto1.proto:16:14: "proto.AnotherProto" is not defined.
proto1.proto:40:14: "AnotherProto" is not defined.
如果我把another_proto.proto
放在proto1.proto
前面,我会得到以下错误:
proto/another_proto.proto: File not found.
proto1.proto:7:1: Import "proto/another_proto.proto" was not found or had errors.
proto1.proto:16:14: "proto.AnotherProto" seems to be defined in "another_proto.proto", which is not imported by "proto1.proto". To use it here, please add the necessary import.
proto1.proto:40:14: "proto.AnotherProto" seems to be defined in "another_proto.proto", which is not imported by "proto1.proto". To use it here, please add the necessary import.
然后,如果我删除--proto_path=proto
并在每个protobuf
前面添加proto\
,我不会得到这些错误,但生成的文件将被放置在out\proto
中,这非常令人困惑,因为我认为--go_opt=paths=source_relative
告诉protoc
将输出放在protobuf
的位置,如这里所述,在我的情况下是文件夹proto
。
如果指定了paths=source_relative标志,则输出文件将与输入文件放在同一相对目录中。例如,输入文件protos/buzz.proto会导致输出文件protos/buzz. pb. go。
我尝试使用--go_out=proto/out
,但恼人的是它将生成的文件放在proto/out/proto
中。我猜这是因为protobuf
前面的proto/
,因为前面提到的错误,我可能不得不坚持out/proto
现在,因为它是目前最明智的路径。
更新:
我不太确定我是否正确地理解了@Daz,但这是我对你的指示的解释。
所以我对Proto1
做了以下修改:
package src;
option go_package = "github.com/me/golang-grpc-server/proto/src";
import "src/another_proto.proto";
message Proto1 {
...
...
repeated src.AnotherProto another_proto = 6;
}
我将所有其他protobufs移动到proto
下的一个文件夹中,当然将每个protobufs的go_package
更改为最后的/src
,并更改了导入部分以反映更改。然后我将protoc
命令修改为:
protoc --proto_path=proto/src --go_out=./out --go_opt=paths=source_relative --go-grpc_out=./out --go-grpc_opt=paths=source_relative proto/src/*.proto
*
太棒了。同样的事情在这里,修改它,以反映所做的更改文件夹结构。不幸的是,从protobuf
本身开始,这些更改不起作用。import
似乎不承认go_package
或package
中的更改。如果我使用“src/another_proto.proto”作为导入路径,linter会说路径“not found or has errors”。然后当我使用“proto/src/another_proto.proto”时,错误就消失了,但是当我运行protoc
时,它会抛出以前的“not found...”错误。
更新:
伙计,这是一些非常令人愤怒的情况,可能是由protoc go
上的bug或缺少功能引起的。因此,我试图将命令推送到一个更符合逻辑的目录中,因此我修改了protoc
命令,使其具有更长的--proto_path
,因为我认为这样做可以将文件夹修剪到最终的输出路径。每次我添加一个文件夹到--proto_path
,我修改了protobuf
的go_package
和import
以及,因为错误“找不到”protobuf
会出现。在我当前的命令中,protobufs
看起来像这样:
package src;
option go_package = "github.com/me/golang-grpc-server/proto/src";
import "another_proto.proto";
message Proto1 {
...
...
repeated AnotherProto another_proto = 6;
}
看起来很漂亮但是,林特不喜欢它。我猜,正如@Daz提到的,因为protobuf
并没有真正使用Golangs
包系统,所以linter不知道如何引用import
。现在,我有一个项目,我认为应该建立,但有2个文件的错误。这是我当前的命令,它将存根放在与proto
文件夹相同级别的另一个文件夹中:
protoc --proto_path=proto/src --go_out=out --go_opt=paths=source_relative --go-grpc_out=out --go-grpc_opt=paths=source_relative proto/src/*.proto
2条答案
按热度按时间vnjpjtjt1#
是的,很有挑战性。
好消息是:一旦你理解了这个过程,它就会始终如一地工作。我在Linux上使用Golang,Rust和Python的方法,它对我很有效。
1. Protobuf源、包和文件夹
Protobuf源文件定义了一个包(!)层次结构。
我将使用Google的Well-known Types (WKT)作为示例。这些文件位于protobuf(!)包
google.protobuf
。安装protoc
时,通常这些文件也安装在一个名为include
的文件夹中,每个WKT例如Timestamp.proto
存在于从package
名称(!):因此Protobuf包路径Map到文件系统文件夹路径**,但**它们必须锚定在某个文件系统文件夹上(例如
include
在这种情况下)。此根文件夹{SOME-FOLDER}/include
是protoc
中的proto_path
值。并且希望在这个根文件夹下导入protos的来自其他proto源的包引用是相对于这个proto_path
值作为根的,例如。import "google/protobuf/timestamp.proto";
(无include
,但必须反映此根目录的文件夹路径)。2.编译后的protos(stub)、包和文件夹
Protobuf支持编译成多种语言,每种语言都有其独特的特点。既然你问了Golang,我就提供Golang的答案。
Protobuf和Golang在包命名上有相似之处,但重要的是要记住-在许多情况下-protobuf源代码(!)
package
不一定Map到语言的包。对于Golang,你必须告诉protoc你想要使用的Golang包:
WKT
Timestamp
由GoogleTimestamppb
在google.golang.org/protobuf/types/known/timestampb
包中实现(与google.protobuf
完全无关所以...
在你的例子中,我认为你应该删除protobuf源代码中的
proto
引用,因为这个文件夹代表你的项目层次结构而不是protobufpackage
层次结构。如你有(!)父文件夹(!)成为你的
proto_path
,因为你的包层次结构从proto
开始(或者你有proto/proto
,这会让人困惑):或者,正如我所推荐的(!)您可以选择另一个软件包
foo
(或删除该软件包),继续将proto_path
锚定在${SOME_FOLDER}/proto
上并更正导入机制:some.proto
:使用
--go_opt=paths=source_relative
很常见,但我的首选(主要是因为它对我有意义)如下:因为所有内容都在
${PWD}/proto/foo
下,所以您也可以只使用${PWD}/proto/foo/*.proto
。产量:
j2cgzkjk2#
最后,感谢@DazWilkin最初的回答,我终于找到了做我想做的事情的命令。这就是:
我认为这里最重要的一点是
--proto_path
。使它有确切的文件夹,我的protobuf
的,使我能够使用任何--go_out
,我想。所以protoc
不需要添加--proto_path
中缺少的附加/前导文件夹,如果它不是确切的文件夹。然后在
protobuf
s上,你必须这样做:正如我上次更新中提到的,linter似乎不喜欢这样,因为它可能不知道如何在这种设置中处理
protobuf
。