[PYTHON] Make Fatjar by changing the main class with Gradle

Purpose

There was a library that could only be used in Java, and there was an existing application that implemented it in Kotlin. This time I wanted to call some of the features from a Python batch and use them, so Change the main class of Kotlin application to make a jar, I wanted to hit Kotlin with a java command from Python.

It seems that if you use Gradle well, you can change the main class and make Fatjar. I will challenge

environment

Kotlin JDK 8 java8 jdk14 Gradle 6.4.1

Construction

I tried to create a simple project to try

app
├── gradle
│   └── wrapper
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
├── build.gradle
└── src
    ├── main
    │   ├── kotlin
    │   │   └── automated_data_create
    │   │       ├── App.kt
    │   │       ├── App2.kt
    │   │       └── model
    │   │           └── Osushi.kt
    │   └── resources
    └── test
        ├── kotlin
        │   └── automated_data_create
        │       └── AppTest.kt
        └── resources

app/src/main/kotlin/automated_data_create/App.kt


/*
 * This Kotlin source file was generated by the Gradle 'init' task.
 */
package automated_data_create

import automated_data_create.model.Osushi

class App {
    val greeting: String
        get() {
            return "Hello world."
        }

}

fun main(args: Array<String>) {
    println(App().greeting)
    val osushi = Osushi("Tuna", 100)
    println("I have selected this.: " + osushi.name + " -> " + "¥" + osushi.price)
}

app/src/main/kotlin/automated_data_create/App2.kt


/*
 * This Kotlin source file was generated by the Gradle 'init' task.
 */
package automated_data_create

import automated_data_create.model.Osushi


class App2 {
    val greeting: String
        get() {
            return "Hello world."
        }

}

fun main(args: Array<String>) {
    println(App2().greeting)
    val osushi = Osushi("Sea urchin", 200)
    println("I have selected this.: " + osushi.name + " -> " + "¥" + osushi.price)
}

app/build.gradle


/*
 * This file was generated by the Gradle 'init' task.
 *
 * This generated file contains a sample Kotlin application project to get you started.
 */

plugins {
    // Apply the Kotlin JVM plugin to add support for Kotlin.
    id 'org.jetbrains.kotlin.jvm' version '1.3.61'

    // Apply the application plugin to add support for building a CLI application.
    id 'application'
    id 'com.github.johnrengelman.shadow' version '5.0.0'
    id 'java'
}

repositories {
    // Use jcenter for resolving dependencies.
    // You can declare any Maven/Ivy/file repository here.
    jcenter()
}

dependencies {
    // Align versions of all Kotlin components
    implementation platform('org.jetbrains.kotlin:kotlin-bom')

    // Use the Kotlin JDK 8 standard library.
    implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'

    // Use the Kotlin test library.
    testImplementation 'org.jetbrains.kotlin:kotlin-test'

    // Use the Kotlin JUnit integration.
    testImplementation 'org.jetbrains.kotlin:kotlin-test-junit'
}

application {
    // Define the main class for the application.
    mainClassName = 'automated_data_create.AppKt'
}

Create a jar file with the main class as it is

You can build the project with the following command

$ ./gradlew shadowJar
# or
$ gradle shadowJar

In this case, since the AppKt file is specified in mainClassName in the app / build.gradle file, App.kt runs as the main class.

Command to execute the built jar

$ java -jar xxx-1.0-SNAPSHOT-all.jar
Hello world.
I have selected this.:Tuna-> ¥100

Build by changing the main class to another class

Add the build task to your gradle.build file.

app/build.gradle


:
application {
    // Define the main class for the application.
    mainClassName = 'automated_data_create.AppKt'
}
#Add below from here ↓
task customFatJar2(type:Jar) {
    //Main class settings
    manifest {
        attributes 'Main-Class': 'automated_data_create.App2Kt'
    }
    baseName = 'second'
    //Add dependent libraries
    from { configurations.compileClasspath.collect { it.isDirectory() ? it : zipTree(it) } }


    with jar
}

Here, the main class is specified as App2.Kt. Specify any jar file name for baseName.

Note that how to add dependent libraries depends on the version of gradle.

compile: Get the compile set in dependencies as a list.

compileClasspath: Get the dependencies registered in implementation etc. in a list.

Reference: How to use compile and implementation properly     https://qiita.com/opengl-8080/items/6ad642e0b016465891de It was easy to see what cofigrations.compile and configurations.compileClasspath looked like     https://qiita.com/MirrgieRiana/items/d3271f6979c1451207a6

--Execute gradle task

$ ./gradlew customFatJar2
or
$ gradle customFatJar2

Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/6.4.1/userguide/command_line_interface.html#sec:command_line_warnings


BUILD SUCCESSFUL in 1s

--Jar execution

$ java -jar build/libs/second.jar
Hello world.
I have selected this.:Sea urchin-> ¥200

At the end

Now that you can hit Kotlin applications with java commands, All we have to do now is run it from Python! By the way, from Python I plan to run it using the subprocess library. Please let me know if there is a better way!

Recommended Posts

Make Fatjar by changing the main class with Gradle
Change the movement by changing the combo box with tkinter
Make the Python console covered with UNKO
Install by specifying the version with pip
When changing the table name with flask_migrate
Make the library created by Eigen in C ++ available from Python with Boost.Numpy.
Recreate the django staff registration screen with class
Broadcast operation by raising the dimension with np.newaxis
Save the output of conditional GAN for each class ~ With cGAN implementation by PyTorch ~