Import Files in Protocol Buffer

2020 Nov 20

A Java project contains protocol buffer files (to define gRPC API). It uses protobuf-gradle-plugin to compile the protocol buffer files. By default this Gradle plugin reads protocol buffer source files from the src/main/proto/ directory.

The structure of the src/main/proto/ is like below.

.
├── foo
│   ├── bar
│   │   └── def.proto
│   ├── common
│   │   └── common.proto

Assume in the foo/bar/def.proto file, it needs to import message types defined in the foo/common/common.proto file. To do it, in the foo/bar/def.proto file, add lines like below.

syntax = "proto3";

package foo.bar;

import "foo/common/common.proto";

message BarType {
    // use full qualified name to refer to CommonTypeA, not just `CommonTypeA`
    // (assume the package name is "foo.common")
    foo.common.CommonTypeA a = 1; 
}

A import statement using relative path like import "../../common.proto"; does not work. Because the protocol compiler does not search files in the “upper” directories. It only searches in directories provided by the -I/--proto_path options or the directory in which the compiler was invoked if the -I option not given.

The protocol compiler searches for imported files in a set of directories specified on the protocol compiler command line using the -I/–proto_path flag. If no flag was given, it looks in the directory in which the compiler was invoked. In general you should set the –proto_path flag to the root of your project and use fully qualified names for all imports.

The protobuf-gradle-plugin sets src/main/proto/ to the -I option when invokes protoc. It can be observed from the Gradle info log, ./gradlew build -i. Therefore, for the statement import "foo/common/common.proto";, the protoc will successfully find the imported file under the foo/common directory of the src/main/proto/.

(Usually IntelliJ IDEA knows that the src/main/proto/ is the path to search imported files. If not, add “Custom include paths” in Preferences -> Protobuf Support.)

More documentation about the --proto_path=IMPORT_PATH option.

IMPORT_PATH specifies a directory in which to look for .proto files when resolving import directives. If omitted, the current directory is used. Multiple import directories can be specified by passing the --proto_path option multiple times; they will be searched in order. -I=_IMPORT_PATH_ can be used as a short form of --proto_path.