はじめに
miseを実務で使っていて、Gradleのマルチプロジェクトとは相性が悪いことに気づいたので、書き残しておきます。
miseの使い方や、そもそもmiseとは何かの話は、過去に書いた↓の記事を参考にしてください。
miseでサブプロジェクトのバージョン管理はできない
Gradleのマルチプロジェクトだと、miseでのバージョン管理はうまくいきません。
具体的に何が言いたいかと言うと「サブプロジェクトごとにmiseでバージョンを切り替える」という使い方は難しい、ということです。
mise
の設定スコープはカレントディレクトリが基準
miseには、mise.toml
という設定ファイルにツールやバージョンを記載してプロジェクト内に配置することで、チームでの開発環境共有を簡単に行える仕組みがあります。カレントディレクトリから親ディレクトリ方向へ探索していき、最初に見つかったものが優先される仕様です。
この仕組みのおかげで単にプロジェクトを移動するだけでツールやランタイムのバージョンを切り替えられるのですが、これはGradleのマルチプロジェクト構成とは相性が悪いです。
ルートプロジェクトの下に2つのサブプロジェクトがある場合を例に説明します。
root-project/
├── build.gradle.kts
├── gradlew # ここが起点
├── mise.toml # ← この設定が全体に適用される
├── settings.gradle.kts
├── sub-project-a/
│ ├── build.gradle.kts
│ └── mise.toml # ← これは読み込まれない
└── sub-project-b/
├── build.gradle.kts
└── mise.toml # ← これも読み込まれない
サブプロジェクトがいくつあっても、gradlew
はルート直下にしかありません。つまりGradleを実行する際は常にルート直下が起点になります。
このため、sub-project-a
とsub-project-b
で別々にバージョン管理をしたいと思い、それぞれにmise.toml
を配置しても、gradlew
のあるルート直下やそれより上(親ディレクトリ方向)しか探索されないので、サブプロジェクトの設定ファイルが読み込まれることはありません。
結果、ルート直下のmise.toml
(あるいはグローバル設定)だけが使われます。
開発者のローカル端末内に限れば、サブディレクトリへ移動してからGradleを動かせば、そのディレクトリのmise.toml
が読まれるでしょうが、その時点で「複数プロジェクトをまとめてビルドする」という本来の目的から外れるので本末転倒です。
じゃあどうしたらいいの?
こうした問題がある以上、無理にmiseを使うのではなく、Gradle標準の仕組みを活用するのが現実的だと思います。
まずJDKについては、Java Toolchains
を使えば「Gradle自体が使うJDK」と「各サブプロジェクトで使われるJDK」はそれぞれ別に管理できます。
また、各種ライブラリなどの依存関係やそれらのバージョンは、サブプロジェクトごとのビルドスクリプト(build.gradle
やbuild.gradle.kts
)で置き換えられます。
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(17))
}
}
dependencies {
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.14.0")
...
}
このように、マルチプロジェクト構成では潔くGradleの機能で完結させるのが現実的かと思います。
miseはもちろん便利なツールなのですが、カレントディレクトリを基準にして管理するその特性上、マルチプロジェクト構成とは合いませんでした、というお話でした。