在.proto文件中使用import时出错。

87

我尝试使用import语句将名为test1.proto的proto文件导入到另一个名为test2.proto的proto文件中。

import "com/test/test1.proto";

但是我遇到了以下错误

com/test/test1.proto: File not found.
test2.proto: Import "com/test/test1.proto" was not found or had errors.

我已经尝试了很多方法来找到导入错误的原因,但是没有成功。所以请问有人能告诉我正确的proto文件导入方式吗?假如以上说法有问题。

7个回答

76

您需要使用命令行标志--proto_path(也称为-I)告知protoc查找.proto文件的位置。如果您没有提供路径,默认情况下它只会搜索当前目录。请参见文档(页面末尾的“生成类”部分),或键入protoc --help


2
这意味着在导入语句中只需要提到proto文件的名称吗?当我执行导入时,会出现以下错误:“该文件不驻留在使用--proto_path(或-I)指定的任何路径内。 您必须指定一个包含此文件的--proto_path。 请注意,proto_path必须是.proto文件名称的精确前缀--protoc无法确定两个路径(例如绝对和相对路径)何时等效(这比您想象的更难)。 "请澄清一下。 - Aarish Ramesh
protoc -I=第一个导入文件的路径 -I=第二个导入文件的路径 --cpp_out=输出文件所在路径 输出文件所在路径/文件名.proto - spfursich
36
如果您的.proto文件位于foo/bar/baz/qux.proto,则您的--proto_path可以是.foofoo/barfoo/bar/baz中的任何一个,但不能是corge,也不能是/absolute/path/to/foo/bar/baz等,因为它们不是文件名的前缀。这个想法是proto路径应该指定您的“顶级源目录”,即所有导入相对于的目录。所以如果您将此文件作为import "baz/qux.proto"导入,则您的proto路径应该是foo/bar - Kenton Varda
1
如果您正在使用预编译的Java Maven Proto文件Jar来导入,那么您在哪里可以提及这个Proto文件的路径? - Righto
@Righto 根据我可能过时的了解,协议编译器无法从 .jar 文件中读取 .proto 文件,抱歉。 - Kenton Varda
1
可以通过多次传递 --proto_path 选项来指定多个导入目录;它们将按顺序进行搜索。 - Nitin Savant

39

另外需要补充的是,如果您正在为 .NET 构建项目和/或使用 Visual Studio,您可以在 .csproj 文件中为 proto 文件定义添加额外属性以指定 Proto 根目录,方法如下:

<Protobuf Include="Protos\ProtoFile.proto" GrpcServices="None" ProtoRoot="Protos\" /> 

这将清除所有导入和相关的错误。


谢谢您。我已经试图弄清楚我缺少了什么好几个小时了。 - thornhill
1
ProtoRoot也必须是Include路径的前缀,以防有人仍然感到困惑。ProtoRoot应该只是从.csproj到protos目录的相对路径。一旦这样做了,您就可以直接导入另一个proto,例如在某个其他proto中导入“base.proto”,只要它们共享相同的目录和包。 - perustaja
@perustaja 出于好奇,定义不同包的协议如何工作? - Matthew Heimlich
@MatthewHeimlich 我已经有一段时间没碰这些协议了,所以我不能确定。 如果您想看看它的工作方式,我可以向您提供存储库的链接。 我最近没有检查过,但那时我无法在任何地方找到关于此csproj设置的严格文档。 - perustaja
这对我非常有用,因为我的导入文件比.proto文件高一级,而Visual Studio找不到它。谢谢! - tank104

23
如果您正在使用IntelliJ IDEA,打开 偏好设置 -> Protobuf 支持 并添加您的.proto文件路径。这样可以解决错误。

1
我可以在IntelliJ IDEA的选项中仅提供路径(文件夹)信息。当.proto.jar中时,有没有一种方法可以使用呢?我想使用位于..\plugins\protobuf-jetbrains-plugin\lib\protobuf-java-3.6.1-sources.jar的jar包中的google.protobuf.Empty - Muka

2

对于运行Bazel项目的人来说,可以在BUILD文件的deps字段中添加所需的proto文件,如下所示-

native.proto_library(
    name = "test_message"
    srcs = "test_message.proto"
    deps = "//path/to/proto/you_are/importing:test1"

test1test1.proto 文件的目标名称,就像 test_messagetest_message.proto 文件的目标名称一样。


回应一个旧评论,但是...在.proto文件中我的导入语句是什么?我无法让它工作,它一直说找不到文件。 - Jdban101

1
假设在类 Unix 的环境下,proto 文件的路径为 /home/path/to/the/protos/dir。proto 文件中包含以下 package 和 import 语句:
package protos.dir;
import "protos/dir/sample.proto";

...

现在进入 proto 包的上一级目录,并执行如下命令进行 proto 编译:
$ cd /home/path/to/the
$ protoc --proto_path=/home/path/to/the --python_out=. /home/path/to/the/protos/dir/*.proto

0

如果您正在使用IntelliJ:

  1. 单击右侧标题上的Maven选项卡。
  2. 单击重新加载所有Maven对象,它将由一个圆形符号表示。

0

需要注意以下几点:

  1. protoc 正在尝试从 proto-path 中找到 com/test/test1.proto(默认情况下,它将是当前工作目录)
  2. 为了编译 test2.proto 并使 protoc 能够从 proto-path 中找到 com/test/test1.proto,必须满足以下条件:--proto-path="<working_directory; absolute path to wd 1 level above com/test>"
  3. protoc --go_out=pb --go_opt=paths=source_relative --go-grpc_out=pb --go-grpc_opt=paths=source_relative com/test/test2.proto --proto_path=<working_directory>
  4. 这样,protoc 就会查找 <working_directory> 级别,并能够找到 com/test/test1.proto

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接