Gradle:同一项目中的 Java/Kotlin、C++、ProtoBuf

Mar*_*wan 5 c++ protocol-buffers gradle kotlin

我有一个 Java+Kotlin 应用程序,使用 Gradle 构建。

它的一些低级功能由单独的 C++ 应用程序提供。

这两个应用程序使用协议缓冲区和 gRPC 通过套接字或管道进行通信。

起初,我所希望的一个项目,建立三个(protobuf的生成代码,Java应用程序,C ++应用程序),但是cpp-applicationjava对某些任务冲突(编译/实施/测试?)。

从那以后,我将其分为三个项目:

/
 build.gradle
 settings.gradle
 cpp-app/
         build.gradle
         settings.gradle
         ...
 java-app/
          build.gradle
          settings.gradle
          ...
 protocol/
          build.gradle
          settings.gradle
          build/generated/source/proto/main/java/...   <-- Java generated code
          build/generated/source/proto/main/cpp/...    <-- C++ generated code
          ...
Run Code Online (Sandbox Code Playgroud)

我的protocol项目成功生成了 C++ 和 Java 实现。

如何让 C++ 和 Java 应用程序项目解析并在其构建中使用这些输出?

Mar*_*wan 4

我在写问题时解决了这个问题。

gradle配置文件如下所示。有几个冗余块对于本示例来说是不需要的(或者根本不需要),但是它们实现了目标。

/build.gradle

subprojects {
        group = 'com.whatever.your.group'
        version = '0.0.0'
        repositories {
                mavenCentral()
        }
}
Run Code Online (Sandbox Code Playgroud)

/设置.gradle

rootProject.name = 'my-project'
include 'java-app'
include 'cpp-app'
include 'protocol'
Run Code Online (Sandbox Code Playgroud)

/java-app/build.gradle

buildscript {
        repositories {
                mavenCentral()
        }
        dependencies {
                classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.20"
        }
}

plugins {
        // Java
        id 'maven'
        id 'idea'
        id 'application'
        id 'java'
        id 'org.jetbrains.kotlin.jvm' version '1.3.20'

        // ProtoBuf
        id 'com.google.protobuf' version '0.8.8'
}

description = """"""

sourceCompatibility = 8
targetCompatibility = 8

compileKotlin {
        kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
        kotlinOptions.jvmTarget = "1.8"
}

mainClassName = 'my.main.Class'

dependencies {
        protobuf project(':protocol') // <-- name of protobuf project
        compile project(':protocol')  // <-- name of protobuf project
        // We have "protobuf" and "compile", as "compile" brings in transitive dependencies

        testCompile 'junit:junit:4.12'

        implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.20"

        testImplementation "org.jetbrains.kotlin:kotlin-test:1.3.20"
        testImplementation "org.jetbrains.kotlin:kotlin-test-junit:1.3.20"
}

sourceSets {
        main {
                java {
                        srcDir "src/main/java"
                }
                kotlin {
                        srcDir "src/main/kotlin"
                }
        }
}
Run Code Online (Sandbox Code Playgroud)

/java-app/settings.gradle

rootProject.name = 'java-app'
Run Code Online (Sandbox Code Playgroud)

/cpp-app/build.gradle

plugins {
        id 'maven'
        id 'cpp'
}

description = """"""

project.tasks.build.dependsOn 'protocol'  // <-- name of protobuf project

model {
        components {
                main(NativeExecutableSpec) {
                        ...
                }
        }
        ...
}
Run Code Online (Sandbox Code Playgroud)

/cpp-app/settings.gradle

rootProject.name = 'cpp-app'
Run Code Online (Sandbox Code Playgroud)

/协议/build.gradle

plugins {
        id 'maven'
        id 'java'
        id 'com.google.protobuf' version '0.8.8'
}

repositories {
        mavenCentral()
}

description = """"""

sourceCompatibility = 8
targetCompatibility = 8

dependencies {
        compile 'com.google.protobuf:protobuf-java:3.7.0'
        compile 'io.grpc:grpc-stub:1.19.0'
        compile 'io.grpc:grpc-protobuf:1.19.0'
}

sourceSets {
        main {
                proto {
                        srcDir "src/main/proto"
                }
        }
}

protobuf {
        protoc {
                artifact = "com.google.protobuf:protoc:3.7.0"
        }
        plugins {
                grpc_java {
                        artifact = 'io.grpc:protoc-gen-grpc-java:1.19.0'
                }
                grpc_cpp {
                        path = getPluginPath('cpp')
                }
                grpc_python {
                        path = getPluginPath('python')
                }
        }
        generateProtoTasks {
                generatedFilesBaseDir = "${buildDir}/build/generated/src"
                all()*.builtins {
                        java { }
                        cpp { }
                        python { }
                }
                all()*.plugins {
                        grpc_java {
                                outputSubDir = 'java'
                        }
                        grpc_cpp {
                                outputSubDir = 'cpp'
                        }
                        grpc_python {
                                outputSubDir = 'python'
                        }
                }
        }
}

clean {
        delete protobuf.generatedFilesBaseDir
}

// Used to find executables for generating C++ and Java gRPC
static def getPluginPath(name) {
        def path = "which grpc_${name}_plugin".execute()
        path.waitFor()
        path = path.in.text.trim()
        if (!path) {
                println "Failed to locate GRPC plugin for ${name}"
        } else {
                println "Found GRPC plugin for ${name} at ${path}"
        }
        return path
}
Run Code Online (Sandbox Code Playgroud)

/协议/settings.gradle

rootProject.name = 'protocol'
Run Code Online (Sandbox Code Playgroud)

然后在项目根目录中,我可以运行gradle assemble, 并且:

subprojects {
        group = 'com.whatever.your.group'
        version = '0.0.0'
        repositories {
                mavenCentral()
        }
}
Run Code Online (Sandbox Code Playgroud)