Gradleのcompileとruntimeコンフィギュレーションの違いは何か?

2018年8月23日

Gradleの標準的なコンフィギュレーションとして、compileとruntimeの二つが用意されているのだが、この違いは何だろう?

例えば、マニュアルの8.3. 依存関係のコンフィグレーション にはこうある。

compile
プロジェクトのプロダクトコードをコンパイルするのに必要な依存関係
runtime
プロダクトのクラスを実行するときに必要になる依存関係。デフォルトで、コンパイル時の依存関係もここに含まれる。

この説明でわかる人間がいるんだろうか?私には理解できない。コンパイル時は不要だが、実行時には必要になる依存とは一体何だろう???もしかしたら、Mavenをやっていた人には常識なのかもしれないが、私はほとんどいじったことがない。

Stackoverflowでの答え

Difference between compile and runtime configurations in Gradleに答えてくれている人がいた。

質問:

少しありがちかもしれないけど、これもGradleに関係してるんだ。
なぜ、compileとruntimeのコンフィギュレーションが必要なのだろう?
何かをコンパイルする場合、自分のJavaクラスをバイトコードに変換するのにアーティファクトが必要だ。だから、compileコンフィギュレーションはいるよね。しかし、なぜruntimeコンフィギュレーションが必要なんだろう?このアプリをJVM上で動かすのに、他のものがいるのかな?
馬鹿みたいに聞こえたらごめん、しかし理解できないんだ。

答え:

もっともありがちなケースとしては、コンパイル時に必要なアーティファクトは実行時に必要なものの一部なんだ。
例えばだね、appというアプリがfooライブラリを必要とする。そして、fooは内部的にbarを必要とするとする。だから、appのコンパイル時にはfooしか必要無い。しかし、fooとbarが両方共実行には必要だ。だから、デフォルトでは、Gradleのcompileに入れたものすべてがruntimeコンフィギュレーションでも見えることになるんだが、しかし逆は真ではない。

私の考え

理屈はわかったのだが、そんな必要あるのか?実行時にbarが必要であれば、compileにbarを含めることに何の問題があるのだろうか?

それと、そもそも、どのタスクがruntimeを参照しているのだろうか?これについても第23章 Javaプラグインを読んでみたところでは、すぐにはわからない。もしかしたら書いてあるのかもしれないが。。。

もちろん、自作のタスクでruntimeを利用することはありうるだろうが、他に必要なものがあるならその時点で追加すればいい話だろう。

ともあれ、こういった機能をつけるのは良いとしても、適切な説明がされていない。具体的にどんなケースで必要になるのかさっぱりわからないので、結局は納得の行くものになっていない。もしかしたらMavenにあるからという理由だったりするのだろうか?