Gradleマルチプロジェクトでは、Mavenリポジトリは絶対パスで指定すべきだった話

こんにちは、エキサイト株式会社の平石です。

今回は、Gradleでマルチプロジェクトを構成している状態で、MavenのLocalRepositoryを指定する際にハマった内容を紹介します。

デフォルト以外のLocalRepository

今回は、repositoriesの設定で独自のRepositoryを指定することを目的としていました。

Maven Repositoryに上げられているようなグローバルに公開されているライブラリを利用する際には、

repositories {
    mavenCentral()
}

のように記述します。

ローカルにあるRepositoryを設定したい場合には

repositories {
    mavenLocal()
}

のように記述します。
デフォルトでは、LocalRepositoryは$USER/.m2/repositoriesにあります。

しかし、時にはプロジェクトごとに分けたいという理由で別のローカルリポジトリを指定したい場合もあります。

今回は、local_repositoryというディレクトリをプロジェクトルート直下に作成して、そこにライブラリを入れているとします。

この場合、build.gradleに以下のように記述することで、指定することができます。

repositories {
        maven {
            url "./local_repository"
        }
    }

urlには、サーバー上のリポジトリやS3のようなオブジェクトストレージにあるライブラリへのパスを記述できますが、ローカル環境にあるリポジトリの場所を指定することもできます。

以下のように、プロジェクトに依存関係を追加することができます。

dependencies {
    implementation "com.example.rh:sample:0.0.1-SNAPSHOT"
}

このように一つのプロジェクト内のみでの設定であれば問題ないのですが、allprojectssubprojectsを利用して複数のプロジェクトに対して設定を行おうとしたときにハマってしまいました。

以下が、ハマったときのプロジェクトルート直下のbuild.gradleの全体です。

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.2.1'
    id 'io.spring.dependency-management' version '1.1.4'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'

java {
    sourceCompatibility = '21'
}

allprojects {
    repositories {
        mavenCentral()

        maven {
            url "./local_repository"
        }
    }
}

subprojects {
    apply plugin: 'java'
    apply plugin: 'org.springframework.boot'
    apply plugin: 'io.spring.dependency-management'

    dependencies {
        implementation 'org.springframework.boot:spring-boot-starter'
        implementation 'org.springframework.boot:spring-boot-starter-web'
    }
}

project(':sub_project') {
    dependencies {
        implementation "com.example.rh:sample:0.0.1-SNAPSHOT"
    }
}

allprojectsmavenCentralとプロジェクトルート直下の./local_repositoryからライブラリを取得することを指定しています。
また、:subprojectというサブプロジェクトに./local_repositoryから"com.example.rh:sample:0.0.1-SNAPSHOT"という依存関係を追加しています。

この状態で、gradleプロジェクトをビルドすると、以下のようなエラーが発生します。

:sub_project:main: Could not find com.example.rh:sample:0.0.1-SNAPSHOT.
Required by:
    project :sub_project

com.example.rh:sample:0.0.1-SNAPSHOTが見つからないというエラーのようですが、allprojectsブロックでrepositoriesは指定しているはずです。

これはどういうことでしょうか。
解決法はシンプルで、LocalRepositoryの指定を絶対パスにします。

allprojects {
    repositories {
        mavenCentral()

        maven {
            url "$rootDir/local_repository"
        }
    }
}

allprojectsでLocalRepositoryを指定した際に、その指定したプロジェクトから見たパスで全体に対して取り込まれると勘違いしていました。
しかし、実際には各プロジェクトから見たパスで参照しているようです。

したがって、subprojectというサブプロジェクトはdependency_testの配下にあり、dependency_test/subprojectにはlocal_repositoryというrepositoryが存在しないため、依存関係を解決できなかったようです。

仕様を理解していれば当然の結果ではありました。

終わりに

今回は、マルチプロジェクトにおけるLocalRepositoryを指定する際にハマった内容を紹介しました。

では、また次回。