Home About Contact
Kotlin , Gradle

Gradle を使ってライブラリプロジェクトを作成して local maven に publish、それをアプリケーションプロジェクトで使う(覚え書き)

自分用のちょっとしたライブラリを local maven に publish しておくと便利。 その方法とそれを使う方法。

Kotlin Multiplatform 用のライブラリにしたい場合はこちら「Kotlin Multiplatform プロジェクト用のライブラリの作成と利用」を参照

環境

$ gradle --version

------------------------------------------------------------
Gradle 8.9
------------------------------------------------------------

Build time:    2024-07-11 14:37:41 UTC
Revision:      d536ef36a19186ccc596d8817123e5445f30fef8

Kotlin:        1.9.23
Groovy:        3.0.21
Ant:           Apache Ant(TM) version 1.10.13 compiled on January 4 2023
Launcher JVM:  17.0.12 (Ubuntu 17.0.12+7-Ubuntu-1ubuntu224.04)
Daemon JVM:    /usr/lib/jvm/java-17-openjdk-amd64 (no JDK specified, using current Java home)
OS:            Linux 6.8.0-45-generic amd64

ライブラリを作成

names というポケモン名のリストを返すだけのライブラリをつくります。

$ mkdir names
$ cd names
$ gradle init

質問されるので、答えます。 ライブラリプロジェクトを選択して、kotlin, kotlin.test を選択、JavaVM は 17 を指定しました。

こんな感じです。

$ gradle init
Starting a Gradle Daemon (subsequent builds will be faster)

Select type of build to generate:
  1: Application
  2: Library
  3: Gradle plugin
  4: Basic (build structure only)
Enter selection (default: Application) [1..4] 2

Select implementation language:
  1: Java
  2: Kotlin
  3: Groovy
  4: Scala
  5: C++
  6: Swift
Enter selection (default: Java) [1..6] 2

Enter target Java version (min: 7, default: 21): 17

Project name (default: names): 

Select build script DSL:
  1: Kotlin
  2: Groovy
Enter selection (default: Kotlin) [1..2] 1

Select test framework:
  1: kotlin.test
  2: JUnit Jupiter
Enter selection (default: kotlin.test) [1..2] 1

Generate build using new APIs and behavior (some features may change in the next minor release)? (default: no) [yes, no] no

names プロジェクトは次のようなディレクトリ構成になりました。

$ tree
.
├── gradle
│   ├── libs.versions.toml
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── lib
│   ├── build.gradle.kts
│   └── src
│       ├── main
│       │   ├── kotlin
│       │   │   └── org
│       │   │       └── example
│       │   │           └── Library.kt
│       │   └── resources
│       └── test
│           ├── kotlin
│           │   └── org
│           │       └── example
│           │           └── LibraryTest.kt
│           └── resources
└── settings.gradle.kts

この段階で ./gradlew assemble して作動を確かめます。

問題なければ、./lib/src/main/kotlin/org/example/Library.kt にコードを書きます。

package org.example

class Library {
    val toNames: ()->List<String> = {
        "pikachu,squirtle,charmander,golduck".split(",")
    }
}

再度 ./gradlew assemble します。

テストも書きます。

package org.example

import kotlin.test.Test
import kotlin.test.assertEquals

class LibraryTest {
    @Test fun pokemonNamesTest() {
        val firstPokemonName =  Library().toNames()[0]
        assertEquals("pikachu", firstPokemonName)
    }
}

assertEaulas: https://kotlinlang.org/api/latest/kotlin.test/kotlin.test/assert-equals.html

test タスクを実行して確認します。

$ ./gradlew test

固定のポケモン名のリストを返すだけのライブラリですが、これでライブラリはできました。 これを local maven へ publish します。

そのためには lib/build.gradle.kts を編集します。

// build.gradle.kts

plugins {
    ...
    `maven-publish`
}

...

publishing {
    publications {
        create<MavenPublication>("maven"){
            groupId = "org.example"
            artifactId = "names"
            version = "1.0.0-SNAPSHOT"
            from(components["kotlin"])
        }
    }
}

plugins セクションに maven-publish を追加して、 さらに、publishing セクションを追加しました。

maven-publish を plugin したので、 ./gradlew tasks すると Publishing tasks が出てきます。 publishToMavenLocal タスクを使って実際に local maven にこのライブラリを publish します。

$ ./gradlew publishToMavenLocal

その後、~/.m2/repository/org/example/names を見て実際に local maven に names ライブラリが publish できたか確認しましょう。

Kotlin Script からこのライブラリを使う

作成したライブラリを使う Kotlin Script を書きます。

使用した kotlin :

$ kotlin -version
Kotlin version 2.0.10-release-540 (JRE 17.0.12+7-Ubuntu-1ubuntu224.04)

pokemon.main.kts を用意。

@file:Repository("file://~/.m2/")
@file:DependsOn("org.example:names:1.0.0-SNAPSHOT")

import org.example.Library

val names = Library().toNames()
println(names)

実行します。

$ kotlin pokemon.main.kts 
[pikachu, squirtle, charmander, golduck]

Gradle アプリケーションプロジェクトからこのライブラリを使う

pokemon というプロジェクト名にします。

$ mkdir pokemon
$ cd pokemon
$ gradle init

適当に質問に答えます。アプリケーションプロジェクトを選択して、kotlin, kotlin.test を選択、JavaVM は 17 を指定しました。

$ gradle init

Select type of build to generate:
  1: Application
  2: Library
  3: Gradle plugin
  4: Basic (build structure only)
Enter selection (default: Application) [1..4] 1

Select implementation language:
  1: Java
  2: Kotlin
  3: Groovy
  4: Scala
  5: C++
  6: Swift
Enter selection (default: Java) [1..6] 2

Enter target Java version (min: 7, default: 21): 17

Project name (default: pokemon): 

Select application structure:
  1: Single application project
  2: Application and library project
Enter selection (default: Single application project) [1..2] 1

Select build script DSL:
  1: Kotlin
  2: Groovy
Enter selection (default: Kotlin) [1..2] 1

Select test framework:
  1: kotlin.test
  2: JUnit Jupiter
Enter selection (default: kotlin.test) [1..2] 1

Generate build using new APIs and behavior (some features may change in the next minor release)? (default: no) [yes, no] no

pokemon プロジェクトは次のようなディレクトリ構成になりました。

$ tree .
.
├── app
│   ├── build.gradle.kts
│   └── src
│       ├── main
│       │   ├── kotlin
│       │   │   └── org
│       │   │       └── example
│       │   │           └── App.kt
│       │   └── resources
│       └── test
│           ├── kotlin
│           │   └── org
│           │       └── example
│           │           └── AppTest.kt
│           └── resources
├── gradle
│   ├── libs.versions.toml
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle.kts

app/src/main/kotlin/org/example/App.kt を編集します。

package org.example

class App {
    val greeting: String
        get() {
            return Library().toNames().joinToString(",")
            //return "Hello World!"
        }
}

fun main() {
    println(App().greeting)
}

元から雛形が用意されていたので、それを利用しました。 Hello World! と返すことになっている代わりに、 Library().toNames().joinToString(",") することにしました。

とりあえず run してみます。

$ ./gradlew run

> Task :app:compileKotlin FAILED
e: file:///home/moca/1008-g/pokemon/app/src/main/kotlin/org/example/App.kt:6:20 Unresolved reference: Library

names ライブラリを設定していないので失敗しました。当然の結果です。

app/build.gradle.kts を編集します。

...

repositories {
    mavenCentral()
    mavenLocal()
}

...

dependencies {
    ...
    implementation("org.example:names:1.0.0-SNAPSHOT")
}

repositories セクションに mavenLocal() を追加。 それから、dependencies に先ほど作成した names ライブラリを追加しました。

実行します。

$ ./gradlew run

> Task :app:run
pikachu,squirtle,charmander,golduck

うまくいきました。

まとめ

これでライブラリを作成して、それを Kotlin Script と Gradle Project から使えます。