配置pb编译
pb 插件默认认为 .proto文件跟 java文件组织结构相同,在sourceSets中,在一个sourceSet下的文件使用单独的protoc命令来编译,并将生成的java文件添加到java的sourceSet下作为java编译的输入。
自定义pb文件位置
插件会自动添加proto(跟java并列)下的源码块到对应的sourceSet下。protoc插件默认从src/$sourceSetName/proto
读取并编译,你也可以想自定义java源码所在文件夹一样自定义pb文件所在的文件夹。
java项目配置如下:
sourceSets {
main {
proto {
// In addition to the default 'src/main/proto'
srcDir 'src/main/protobuf'
srcDir 'src/main/protocolbuffers'
// In addition to the default '**/*.proto' (use with caution).
// Using an extension other than 'proto' is NOT recommended,
// because when proto files are published along with class files, we can
// only tell the type of a file from its extension.
include '**/*.protodevel'
}
java {
...
}
}
test {
proto {
// In addition to the default 'src/test/proto'
srcDir 'src/test/protocolbuffers'
}
}
}
android项目配置如下:
android {
sourceSets {
main {
proto {
...
}
java {
...
}
}
}
}
自定义protoc编译器
所有跟 protoc
相关的配置均放在 protobuf
模块下
指定protoc
编译器位置
在没有任何配置的场景下,插件默认会从path中寻找protoc编译器,但是我们推荐直接使用Maven Central上已经编译好的protoc编译器,配置如下:
protobuf {
...
// Configure the protoc executable
protoc {
// Download from repositories
artifact = 'com.google.protobuf:protoc:3.0.0'
}
...
}
你也可以指定本地已经安装的protoc编译器,配置如下:
protobuf {
...
protoc {
path = '/usr/local/bin/protoc'
}
...
}
在 protoc
模块下,可以指定多个配置,但是会以最后一个配置为准。
指定protoc运行插件
protoc在指定plugin名称为foo
时,会默认从path中寻找protoc-gen-foo
来编译。在gradle插件中我们可以跟指定编译器一样在plugins
模块下配置artifact
或者path
。
protobuf {
...
// Locate the codegen plugins
plugins {
// Locate a plugin with name 'grpc'. This step is optional.
// If you don't locate it, protoc will try to use "protoc-gen-grpc" from
// system search path.
grpc {
artifact = 'io.grpc:protoc-gen-grpc-java:1.0.0-pre2'
// or
// path = 'tools/protoc-gen-grpc-java'
}
// Any other plugins
...
}
...
}
注意: 此处仅仅只是声明,在此处配置了在protoc运行时并不会应用插件,如果要想真正的使用,我门需要在generateProtoTasks
模块下使用此处配置的插件。
自定义代码生成任务
插件会为每一个执行的protoc(执行个数根据sourceSet
确定)生成一个任务,每个任务都有 配置输出类型、插件以及protoc参数的接口。所有的配置都放在generateProtoTasks
模块下。
protobuf {
...
generateProtoTasks {
// all() returns the collection of all protoc tasks
all().each { task ->
// Here you can configure the task
}
// In addition to all(), you may select tasks by various criteria:
// (Java-only) returns tasks for a sourceSet
ofSourceSet('main')
// (Android-only selectors)
// Returns tasks for a flavor
ofFlavor('demo')
// Returns tasks for a buildType
ofBuildType('release')
// Returns tasks for a variant
ofVariant('demoRelease')
// Returns non-androidTest tasks
ofNonTest()
// Return androidTest tasks
ofTest()
}
}
注意:
-
不要使用task的名称,因为task名称不是固定的,很有可能会发生改变
-
不要在
generateProtoTasks
外部配置任务,因为配置的任务是有时序性的
每个task下有两个集合:
builtins
protoc编译配置,如果配置生成java、cpp、python等语言
plugins
protoc编译插件配置,如配置grpc插件等。 此处配置的插件必须在 protobuf.plugins
中预先定义
配置生成指定语言的代码
protoc会根据builtins
和plugins
中的配置来生成代码。每个builtin/plugin会生成一种确定格式的代码。添加或者配置只需要列出名称并且后面跟上大括号即可,把配置选项填入大括号内即可。示例:
task.builtins {
// This yields
// "--java_out=example_option1=true,example_option2:/path/to/output"
// on the protoc commandline, which is equivalent to
// "--java_out=/path/to/output --java_opt=example_option1=true,example_option2"
// with the latest version of protoc.
java {
option 'example_option1=true'
option 'example_option2'
}
// Add cpp output without any option.
// DO NOT omit the braces if you want this builtin to be added.
// This yields
// "--cpp_out=/path/to/output" on the protoc commandline.
cpp { }
}
task.plugins {
// Add grpc output without any option. grpc must have been defined in the
// protobuf.plugins block.
// This yields
// "--grpc_out=/path/to/output" on the protoc commandline.
grpc { }
}
编辑器默认配置
Java 项目
插件默认在builtin中指定生成java语言,当使用默认配置时,编译器会自动生成java类
Python项目
在builtin中配置python即可,示例代码:
protobuf {
generatedFilesDir = "$projectDir/generated"
generateProtoTasks {
all().each { task ->
task.builtins {
// Generates Python code in the output folder:
python { }
// If you wish to avoid generating Java files:
remove java
}
}
}
}
Android项目
插件中没有添加默认生成配置,推荐配置java lite库。
在Protobuf 3.0.x-3.7.x版本上,lite代码生成是通过protoc插件方式提供,示例:
dependencies {
// You need to depend on the lite runtime library, not protobuf-java
compile 'com.google.protobuf:protobuf-lite:3.0.0'
}
protobuf {
protoc {
// You still need protoc like in the non-Android case
artifact = 'com.google.protobuf:protoc:3.7.0'
}
plugins {
javalite {
// The codegen for lite comes as a separate artifact
artifact = 'com.google.protobuf:protoc-gen-javalite:3.0.0'
}
}
generateProtoTasks {
all().each { task ->
task.builtins {
// In most cases you don't need the full Java output
// if you use the lite output.
remove java
}
task.plugins {
javalite { }
}
}
}
}
从Protobuf 3.8.0版本之后,lite代码生成器可以直接通过 java 输出选项配置,示例:
dependencies {
// You need to depend on the lite runtime library, not protobuf-java
compile 'com.google.protobuf:protobuf-javalite:3.8.0'
}
protobuf {
protoc {
artifact = 'com.google.protobuf:protoc:3.8.0'
}
generateProtoTasks {
all().each { task ->
task.builtins {
java {
option "lite"
}
}
}
}
}
更改编译代码输出位置
默认生成的java代码输出位置为 $generatedFilesBaseDir/$sourceSet/$builtinPluginName
,其中:
$generatedFilesBaseDir = $buildDir/generated/source/proto
,更改输出配置如下:
protobuf {
...
generatedFilesBaseDir = "$projectDir/src/generated"
}
子目录 $builtinPluginName
可以在builtins或者 plugins模块下配置 outputSubDir属性来修改,示例:
task.plugins {
grpc {
// Write the generated files under
// "$generatedFilesBaseDir/$sourceSet/grpcjava"
outputSubDir = 'grpcjava'
}
}
}
Protos依赖
如果java项目中包含proto文件,他们将跟编译的类一起打包到jar包中。可以通过compile或者protobuf来配置protos依赖。
如果通过compile配置,proto文件将会被提取到extracted-include-protos
目录下,并将此目录添加到protoc命令行运行编译时 --proto_path
参数下,这样就可以把依赖的文件导入到当前工程下。因为导入的proto文件已经在他们原来的工程中编译了,所以当前工程编译时不会编译依赖的proto文件。示例:
dependencies {
compile project(':someProjectWithProtos')
testCompile files("lib/some-testlib-with-protos.jar")
}
如果通过protobuf配置,proto文件会被提取到 extracted-protos
目录下,并被添加到protoc编译文件范围之内,跟编译当前工程的proto文件相同的处理,也就是说此处配置的proto文件依赖会被编译。示例:
dependencies {
// protos can be from a local package,
protobuf files('lib/protos.tar.gz')
// ... a local directory,
protobuf files('ext/') // NEVER use fileTree(). See issue #248.
// ... or an artifact from a repository
testProtobuf 'com.example:published-protos:1.0.0'
}