21

I'd read the documentation but I'm not able to understand how to create a working example to understand better their differences.

enter image description here

And ofc I've created a playground project to check what happens when I use one or another.

app.gradle

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$rootProject.kotlin_version"
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.core:core-ktx:1.2.0'
    compileOnly project(":compileonlylibrary")
    runtimeOnly project(":runtimeonlylibrary")
}

MainActivity.kt

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        FooCompile() // this crash in runtime
        BarRuntime() // this doesn't compiles obviously
    }
}
// FooCompile belongs to compileonlylibrary
// BarRuntime belongs to runtimeonlylibrary

And that's it, I'm stuck here, I'm not able to create a proper example in order to improve my knowledge of Gradle configurations.

Could someone give me a hand? I can provide more details if needed.

Ricardo
  • 7,921
  • 14
  • 64
  • 111

2 Answers2

14
  • implementation: mostly we use implementation configuration. It hides the internal dependency of the module to its consumer to avoid accidental use of any transitive dependency, hence faster compilation and less recompilation.

  • api: must be used very carefully, since it leaks the to consumer’s compile classpath, hence misusing of api could lead to dependency pollution.

  • compileOnly: when we don’t need any dependency at runtime, since compileOnly dependency won’t become the part of the final build. we will get a smaller build size.

  • runtimeOnly: when we want to change or swap the behaviour of the library at runtime (in final build).

I have created a post with an in-depth understanding of each one with Working Example: source code

https://medium.com/@gauraw.negi/how-gradle-dependency-configurations-work-underhood-e934906752e5

Gauraw Negi
  • 561
  • 5
  • 8
11

compileOnly dependencies are available while compiling but not when running them.

This is equivalent to the provided scope in maven.

It means that everyone who wants to execute it needs to supply a library with all classes of the CompileOnly library.

For example, you could create a library that uses the SLF4J API and you could set it to CompileOnly.

Anyone using the library needs to (explicitely) import some version of the SLF4J API in order to use it.

runtimeOnly libraries are the opposite, they are available at runtime but not at compile-time.

For example, you don't need the concrete SLF4J logger(e.g. logback) at compile time (as you use the SLF4J classes in order to access it) but you need it at runtime as you want to use it.

Let's look at the following example:

You have a library that uses the SLF4J:

compileOnly org.slf4j:slf4j-api:1.7.30

and you could have a project using the library:

implementation project(":yourlibrary")
implementation org.slf4j:slf4j-api:2.0.0-alpha1
runtimeOnly ch.qos.logback:logback:0.5

SLF4J detects the concrete logger at runtime, it does not need to know the logging library (like logback) at compile-time. This is why you can use runtimeOnly for the concrete logger.


Note that compileOnly is broadly used with Jakarta EE as lots of dependencies are provided by the JEE container/application server as shown in the blog the OP found.

dan1st
  • 12,568
  • 8
  • 34
  • 67
  • 1
    I understand the differences, my problem is i don't know how to use this knowledge in my benefit. Thats why I would like to have a project example or similar. – Ricardo May 09 '20 at 13:21
  • Ok I've found a very good article https://blog.gradle.org/introducing-compile-only-dependencies about use cases of compileOnly, now I'm looking for runtimeOnly – Ricardo May 09 '20 at 13:27
  • What about my example with the SLF4J logger? – dan1st May 09 '20 at 13:33
  • Are good examples, but i'm looking for something more Android oriented. I've tried `compileOnly org.slf4j:slf4j-api:1.7.30` but if use ´LoggerFactory.getLogger´ then crashs in runtime. Then I've tried using ´implementation and runtimeOnly ´ as you suggests and everything is working fine but I don't know how to they could be used in Android. – Ricardo May 09 '20 at 15:02
  • I am not really into android but https://stackoverflow.com/a/47365147/10871900 suggests that `runtimeOnly` is like `apk`. – dan1st May 09 '20 at 15:07
  • 1
    @dan1st "SLF4J detects the concrete logger at runtime, it does not need to know the logging library (like logback) at runtime" did you mean to write "at compile time" instead of "at runtime" at the end? – kolistivra Jan 12 '21 at 17:14
  • 1
    Yes, my fault, Thank you for the correction. – dan1st Jan 12 '21 at 17:16