I tried running gRPC's Quick Start (Kotlin version), but it was difficult to read the Gradle script.

Overview

I tried running gRPC Quick Start (Kotlin version), but I had never touched Gradle before, and I had a hard time reading Gradle's build script. ..

I don't know who it will be useful for, but I've read it so much that I'd like to make a note of it.

We do not consider the visibility at all. Not bad.

Gradle script I read

The source code for gRPC's Quick Start (Kotlin version) can be found in the following repositories: https://github.com/grpc/grpc-kotlin

There is a "examples" directory in this, and I read the Gradle script in it.

There are Groovy version and Kotlin version in the build script of Gradle, but since the above repository contains the Kotlin version, I read the Kotlin version. (It shouldn't be much different from the Groovy version)

Reading memo

gradle:examples/build.gradle.kts


//This "plugins"{}Is not really a method.
//I think it's a Project method, but it's not.
// 「plugins{}"Consists of the classpath needed to execute other scripts,
// build.It has a special position among the elements that make up gradle.
//gradle is this "plugins"{}When you find
//The classpath is constructed based on the closure defined there.
// see: https://discuss.gradle.org/t/method-for-plugins/37834
plugins {
    //The closure delegate passed to the plugins method is
    //PluginDependenciesSpec object.

    id("com.android.application") version "4.0.0" apply false 
    //Call the id method of PluginDependenciesSpec
    //The version method of the return object (PluginDependencySpec) is called.
    //Then the return object of the version method (PluginDependencySpec, that is, this.)
    //Is calling the apply method of.

    //If false is specified in the apply method,
    //A plugin (a Java class that implements the Plugin interface) is simply added to the classpath.
    //If you want to call the plugin class individually,
    //Specify false for the root project of the multi-project configuration.
    //Especially in the case of multi-project configuration, it is NG to apply in the root,
    //Apply is allowed only in subprojects.
    // see: https://docs.gradle.org/current/userguide/plugins.html#sec:subprojects_plugins_dsl
    //Conversely, if you specify true for the apply method, the apply method of the Plugin interface should be executed.
    //In most cases, the apply method is passed a Project object,
    //Customization such as adding tasks to the Project object is performed.

    //gradle is http://plugins.gradle.org/Plugin to(JAR file)Go looking for.
    //Some plugins, called core plugins, have id("java")Although it is specified by a short name such as
    //Other plugins have the above id("com.android.application")like,
    //Specified by a fully qualified name.

    id("com.google.protobuf") version "0.8.13" apply false


    //The kotlin method is defined in the Kotlin version of PluginDependenciesSpec.
    // see: https://gradle.github.io/kotlin-dsl-docs/api/org.gradle.kotlin.dsl/org.gradle.plugin.use.-plugin-dependencies-spec/kotlin.html
    //The parameter is the module name,"jvm", "js" (=JavaScript), "android"Etc. can be specified.
    //Specifying where to run Kotlin code.
    //Each has different plugins because it's different in what you should do with Gradle.
    // see: https://kotlinlang.org/docs/reference/using-gradle.html
    kotlin("jvm") version "1.3.72" apply false


    id("org.jlleitschuh.gradle.ktlint") version "9.2.1"
}

//The unique property (Extra Properties) is Project.Must be defined in ext.
// see: https://docs.gradle.org/current/dsl/org.gradle.api.Project.html#N15043
ext["grpcVersion"] = "1.32.1"
ext["grpcKotlinVersion"] = "0.2.0" // CURRENT_GRPC_KOTLIN_VERSION
ext["protobufVersion"] = "3.13.0"

// Project.The allprojects method
//About the project (root project) and its subprojects corresponding to this build script
//Call the repositories method of the Project object and set each Project.
allprojects {
    repositories {
        mavenLocal()
        mavenCentral()
        jcenter()
        google()
    }

    apply(plugin = "org.jlleitschuh.gradle.ktlint")
}

//The colon is a directory delimiter, like a slash.
//Previously, the directory delimiter was a slash, but for many reasons it became a colon.
// see: https://qiita.com/opengl-8080/items/4c1aa85b4737bd362d9e#%E5%9F%BA%E6%9C%AC
//In this case, this build.Starting from the directory with gradle
//installDist task in the server subproject
//It depends on (tasks added to the Project by the Application plugin).
//The second colon is a directory, though it's subtle. Well, I understand the meaning.
tasks.create("assemble").dependsOn(":server:installDist")

gradle:examples/client/build.gradle.kts(examples/server/build.gradle.The composition of kts is almost the same as this)


plugins {
    //When you apply the application plugin, the Java Plugin is also applied automatically.
    application

    //There is no need to specify the version because the version specified in the root project is valid.
    //The default true is effective because apply is not specified.
    //So the task is added to the Project object.
    //If you install this Kotlin Gradle plugin,
    //Because "api" Configuration will be available
    //It seems that the Java Library plugin is also applied automatically.
    // see: https://kotlinlang.org/docs/reference/using-gradle.html#dependency-types
    kotlin("jvm")
}

dependencies {
    //Using the "implementation" Configuration introduced by the Java Plugin
    //Grouping dependent libraries.
    implementation(kotlin("stdlib"))
    implementation(project(":stub"))
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.8")

    //Using the "api" Configuration introduced by the Java Library Plugin
    //Grouping dependent libraries.
    //Java Library Plugins by applying Kotlin Gradle plugin
    //It seems that it is applied automatically. s
    //I need a library at compile time,
    //Also required at compile time on the side that uses "artifacts built with this build script" (the concept of API is here),
    //At that time, use this "api" Configuration. Propagating the dependency to the user side.
    api("com.google.protobuf:protobuf-java-util:${rootProject.ext["protobufVersion"]}")

    //runtimeOnly is the Configuration introduced by the Java Plugin.
    runtimeOnly("io.grpc:grpc-netty:${rootProject.ext["grpcVersion"]}")
}

// TaskContainer.In the register method
//Only register a new task in TaskContainer (do not generate and configure)
// see: https://docs.gradle.org/current/userguide/task_configuration_avoidance.html
//You have registered a JavaExec task.
//This is the task of launching the JVM and running a Java application. The closure has that setting.
// see: https://docs.gradle.org/current/javadoc/org/gradle/api/tasks/JavaExec.html
tasks.register<JavaExec>("HelloWorldClient") {
    dependsOn("classes")
    classpath = sourceSets["main"].runtimeClasspath
    main = "io.grpc.examples.helloworld.HelloWorldClientKt"
}

tasks.register<JavaExec>("RouteGuideClient") {
    dependsOn("classes")
    classpath = sourceSets["main"].runtimeClasspath
    main = "io.grpc.examples.routeguide.RouteGuideClientKt"
}

tasks.register<JavaExec>("AnimalsClient") {
    dependsOn("classes")
    classpath = sourceSets["main"].runtimeClasspath
    main = "io.grpc.examples.animals.AnimalsClientKt"
}

//Register a task of type CreateStartScripts
val helloWorldClientStartScripts = tasks.register<CreateStartScripts>("helloWorldClientStartScripts") {
    mainClassName = "io.grpc.examples.helloworld.HelloWorldClientKt"
    applicationName = "hello-world-client"
    outputDir = tasks.named<CreateStartScripts>("startScripts").get().outputDir
    classpath = tasks.named<CreateStartScripts>("startScripts").get().classpath
}

val routeGuideClientStartScripts = tasks.register<CreateStartScripts>("routeGuideClientStartScripts") {
    mainClassName = "io.grpc.examples.routeguide.RouteGuideClientKt"
    applicationName = "route-guide-client"
    outputDir = tasks.named<CreateStartScripts>("startScripts").get().outputDir
    classpath = tasks.named<CreateStartScripts>("startScripts").get().classpath
}

val animalsClientStartScripts = tasks.register<CreateStartScripts>("animalsClientStartScripts") {
    mainClassName = "io.grpc.examples.animals.AnimalsClientKt"
    applicationName = "route-guide-client"
    outputDir = tasks.named<CreateStartScripts>("startScripts").get().outputDir
    classpath = tasks.named<CreateStartScripts>("startScripts").get().classpath
}

//Refer to the StartScripts task of the Application plugin (without generating or configuring) and
//The startScripts task is set to depend on the helloWorldClientStartScripts defined above.
tasks.named("startScripts") {
    dependsOn(helloWorldClientStartScripts)
    dependsOn(routeGuideClientStartScripts)
    dependsOn(animalsClientStartScripts)
}

gradle:examples/stub/build.gradle.kts


import com.google.protobuf.gradle.generateProtoTasks
import com.google.protobuf.gradle.id
import com.google.protobuf.gradle.plugins
import com.google.protobuf.gradle.protobuf
import com.google.protobuf.gradle.protoc

plugins {
    kotlin("jvm")
    id("com.google.protobuf")
}

dependencies {
    protobuf(project(":protos"))

    implementation(kotlin("stdlib"))
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.8")
    implementation("javax.annotation:javax.annotation-api:1.3.2")

    api("com.google.protobuf:protobuf-java-util:${rootProject.ext["protobufVersion"]}")
    api("io.grpc:grpc-stub:${rootProject.ext["grpcVersion"]}")
    api("io.grpc:grpc-protobuf:${rootProject.ext["grpcVersion"]}")
    api("io.grpc:grpc-kotlin-stub:${rootProject.ext["grpcKotlinVersion"]}")
}

java {
    sourceCompatibility = JavaVersion.VERSION_1_7
}

// protobuf-gradle-How to use the plugin is described below.
// see: https://github.com/google/protobuf-gradle-plugin
protobuf {
    //Get the protoc executable from Maven Central.
    protoc {
        artifact = "com.google.protobuf:protoc:${rootProject.ext["protobufVersion"]}"
    }
    //protoc is a compiler, and its role is to generate stub code for a particular language as its output.
    //The codegen plugin is responsible. Below, the codegen plugin is set.
    //By running protoc in combination with codegen in a specific language
    // *.Source code for a particular language is generated from the proto file.
    plugins {
        id("grpc") {
            //As a codegen plugin to generate Java code
            //Declares which version of Maven Central library to use.
            //However, it is only declared here,
            //This description alone does not "apply" the plugin.
            //To apply it, you need to set generateProtoTasks, which will be described later.
            artifact = "io.grpc:protoc-gen-grpc-java:${rootProject.ext["grpcVersion"]}"
        }
        id("grpckt") {
            //Codegen plugin to generate Kotlin code
            artifact = "io.grpc:protoc-gen-grpc-kotlin:${rootProject.ext["grpcKotlinVersion"]}:jdk7@jar"
        }
    }
    // protobuf-gradle-The plugin will generate a task each time you run protoc.
    //You can set what to use as a code generator for this task.
    //In generateProtoTasks, make the settings.
    generateProtoTasks {
        all().forEach {
            //it means a task that is generated each time you run protoc.
            //This task is done with builtins (the code generator that comes with protoc)
            //plugins (a type of code generator combined with protocol)
            //There are two types of properties, and you can set the one you like.
            //Here, as plugins
            //I have two codegen plugins, grpc and grpckt declared above.
            //This setting "applies" these codegen plugins.
            it.plugins {
                id("grpc")
                id("grpckt")
            }
        }
    }
}

[Supplement] Java Plugin

When Java Plugin is applied, Base Plugin is also applied. Applying the Base Plugin adds tasks such as assemble and check to the Project object.

The Java Plugin makes the Base Plugin's assemble task dependent on its own jar task so that when the assemble task is executed, its own jar task is executed.

【reference】 https://docs.gradle.org/current/userguide/base_plugin.html#sec:base_plugin_conventions https://docs.gradle.org/current/userguide/more_about_tasks.html#sec:lifecycle_tasks

In Gradle, there is a concept called Configuration, which is not accurate at all, but roughly represents a group of dependent libraries grouped for a specific purpose. Scope in Maven.

The Java Plugin "implementation" Configuration is a group of dependent libraries used at compile time. In Maven, you could use compile scope etc. without doing anything, but in Gradle you can not do the same without applying Java Plugin.

【reference】 https://docs.gradle.org/current/userguide/declaring_dependencies.html https://docs.gradle.org/current/userguide/dependency_management_for_java_projects.html

Recommended Posts

I tried running gRPC's Quick Start (Kotlin version), but it was difficult to read the Gradle script.
I tried running the Angular sample in Auth0 Quick Start with Docker
[Rails] I tried to raise the Rails version from 5.0 to 5.2
I tried to summarize again the devise that was difficult at first sight
When I started ansible + docker now, I stumbled from the beginning, but I managed to start it
I read the Kotlin startbook
I tried to summarize what was asked at the site-java edition-
I tried to summarize devise which was difficult at first glance
I was addicted to the API version min23 setting of registerTorchCallback
I tried to explain the method
It was a life I wanted to reset the thread-safe associative counter
Since the du command used when the capacity is full is difficult to use, I tried wrapping it with ruby
I was supposed to be looking at JEP 286, but before I knew it, I was implementing Hindley-Milner type inference in Kotlin.