【问题标题】:simple protobuf compilation with gradle使用 gradle 进行简单的 protobuf 编译
【发布时间】:2015-12-25 13:28:41
【问题描述】:

如果您正在寻找示例 gradle protobuf 项目,请查看 here

我很难使用 gradle 和 protobuf, 我想创建一个简单的 gradle 项目,它将从默认的 src/main/protosrc/test/proto 中获取任何 proto 文件并将它们相应地编译为 src/main/javasrc/test/java,然后将其打包到一个 jar 中并发布到本地 repo。

不幸的是,我是 gradle 新手,无法弄清楚原始项目是如何组成的。

这是我未完成的 build.gradle 文件

apply plugin: 'java'
apply plugin: "com.google.protobuf"

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.google.protobuf:protobuf-gradle-plugin:0.7.0'
    }
}

repositories {
    mavenCentral()
}

dependencies {
    compile 'com.google.protobuf:protobuf-java:3.0.0-beta-1'
}

sourceSets {
    main {
        proto {
            srcDir 'src/main/proto'
        }
        java {
            srcDir 'src/main/java'
        }
    }
    test {
        proto {
            srcDir 'src/test/proto'
        }
        proto {
            srcDir 'src/test/java'
        }
    }
}

protobuf {
    // Configure the protoc executable
    protoc {
        // Download from repositories
        artifact = 'com.google.protobuf:protoc:3.0.0-alpha-3'
    }
    generateProtoTasks {
        // all() returns the collection of all protoc tasks
        all().each { task ->
            // Here you can configure the task
        }

        // In addition to all(), you may get the task collection by various
        // criteria:

        // (Java only) returns tasks for a sourceSet
        ofSourceSet('main')

    }
}

运行 jar 任务后,我们有这个:

您可以看到 gradle 将测试和主原型构建到同一个类目录(红色箭头),在 jar 中我可以看到包含两个生成的类(而应该跳过测试)。

但主要问题是我想让 将 proto 文件直接编译到适当的源目录(蓝色箭头),之后普通构建会做正确的事情......毕竟我们需要那些src 中的类以在业务逻辑中使用它们...

所以我们只需要一项将 proto 编译到适当 src 目录的任务......仅此而已。

src/main/proto to src/main/java
src/test/proto to src/test/java

当前项目位于here。请帮忙配置一下,我很确定以后会有很多人需要它...

【问题讨论】:

  • 你能分享一下可运行的例子吗?我知道它不会完成。
  • @Opal github.com/vach/sample-gradle-protobuf 我会把最终的工作版本留在那里供其他人使用
  • @SubOptimal 我做到了,它是一个多项目构建,要使其工作,需要了解整个事情是如何工作的,只需尝试导入它,你就会看到,它甚至不会自己工作,你应该在你能够创建一个项目之前修复一些未解决的依赖项......我只想要一个简单的简约项目......如果你这样做了,请创建一个工作我会尽快理解代码看看吧。
  • @vach,看看这一行:github.com/google/protobuf-gradle-plugin/blob/master/src/main/…。由于 proto 任务已添加到 afterEvaluate 中,您不会在 gradle tasks 输出中看到此任务 - 但它们确实存在。运行gradlew generateProto 并调查build 目录。源被生成。

标签: java gradle build protocol-buffers


【解决方案1】:

如果我没有误解您的问题,那么解决起来很简单。如果您不想区分您自己的源和生成的源,您只需像这样添加设置 generatedFileBaseDir generateProtoTasks.generatedFilesBaseDir = 'src'

所以整个构建文件看起来像:

// ...

protobuf {
// Configure the protoc executable
protoc {
    // Download from repositories
    artifact = 'com.google.protobuf:protoc:3.0.0-alpha-3'
}

generateProtoTasks.generatedFilesBaseDir = 'src' // <- that line 

generateProtoTasks {
    // all() returns the collection of all protoc tasks
    all().each { task ->
        // Here you can configure the task
    }

比你的文件夹看起来像:

  • src/main/java/com/vach/tryout/AddressBookProtos.java
  • src/main/java/com/vach/tryout/protobuf/Main.java

但是: 这可能不是将生成与手工制作的源代码混合的最佳主意。所以我的建议是将源代码生成到一个自己的目录中,例如 generatedSources 并将这个目录添加到 java sourceSet 中。构建文件如下所示:

sourceSets {
    main {
        proto {
            srcDir 'src/main/proto'
        }
        java {
            // include self written and generated code
            srcDirs 'src/main/java', 'generated-sources/main/java'            
        }
    }
    // remove the test configuration - at least in your example you don't have a special test proto file
}

protobuf {
    // Configure the protoc executable
    protoc {
        // Download from repositories
        artifact = 'com.google.protobuf:protoc:3.0.0-alpha-3'
    }

    generateProtoTasks.generatedFilesBaseDir = 'generated-sources'

    generateProtoTasks {
        // all() returns the collection of all protoc tasks
        all().each { task ->
            // Here you can configure the task
        }

        // In addition to all(), you may get the task collection by various
        // criteria:

        // (Java only) returns tasks for a sourceSet
        ofSourceSet('main')

    }   
}

您的目录将如下所示

  • src/main/proto/dtos.proto
  • src/main/java/com/vach/tryout/protobuf/Main.java
  • generated-sources/main/java/com/vach/tryout/AddressBookProtos.java

一个很好的副作用是你可以在你的 git 配置中忽略这个 generated-sources 目录。最好不要发布生成的源代码。

【讨论】:

  • 我不太明白为什么在手工制作的情况下生成代码被认为是不好的,甚至默认行为也会将其分隔到不同的目录...毕竟 protobuf 是一种生成 DTO 的工具,可以有效地序列化和反序列化自身。 ..您在手工代码中使用它们...如果您将它们分开到不同的目录,您需要配置 ide 以了解其他源目录...我真的没有足够的理由这样做...跨度>
  • 我打算使用 protobuf 的方式是创建一个包含所有 DTO 的小项目,该项目将 dtos.jar 暴露给本地 repo,其他项目使用它...
  • @vach 关于您的第一个问题 - 为什么要将生成的代码与“书面代码”分开:这实际上是一个品味问题。您可以在这里找到讨论:[stackoverflow.com/questions/893913/…。除了较小的提交之外,一些可能会意外更改生成的代码。此外,删除类型将变得更加困难(您必须删除您的 proto 文件和 java 文件)。
  • 所以这样做的方法是在其他目录中生成代码(不包含在 vcs 中),但在本地环境中可见。那么任何检查代码的开发人员都会通过 proto 文件获得更新并自己构建它?我希望我画的对吗?我想这也将允许立即检测生成代码中的任何意外手写更改...
  • @vach 我没有遇到你的问题 - 也许你可以更新你的 github 项目(或者只是接受我的拉取请求)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-11
相关资源
最近更新 更多