127

When adding dependencies to my project I am never sure what prefix I should give them, e.g. "classpath" or "compile".

For example, should my dependencies below be compile time or classpath?

Also, should this be in my applications build.gradle or in the module specific build.gradle?

Current build.gradle (at application level):

apply plugin: 'java'

repositories {
    mavenCentral()
}

dependencies {
    compile 'org.hibernate:hibernate-core:5.0.5.Final'
    compile 'mysql:mysql-connector-java:5.1.38'
} 
Eric Wendelin
  • 43,147
  • 9
  • 68
  • 92
java123999
  • 6,974
  • 36
  • 77
  • 121
  • 2
    I'm not sure I understand. `classpath` is not a valid dependency scope. – Tunaki Dec 15 '15 at 10:16
  • Perhaps im getting confused, what are the valid dependency scopes? – java123999 Dec 15 '15 at 10:17
  • Take a look at this document: https://docs.gradle.org/current/userguide/artifact_dependencies_tutorial.html – Tunaki Dec 15 '15 at 10:18
  • One thing i noticed is that `compileOnly` dependencies go to `project.configurations.compileClasspath` but not to `project.configurations.compile`, as mentioned here https://github.com/iboyko/gradle-plugins/issues/5 – Vytenis Bivainis Jul 28 '17 at 19:50

4 Answers4

88

If buildscript itself needs something to run, use classpath.

If your project needs something to run, use compile.

The buildscript{} block is for the build.gradle itself.

For multi-project building, the top-level build file is for the root project, the specific build file is for sub-project (module).

Top-level build file where you can add configuration options common to all sub-projects/modules.

Do not place your application dependencies in top-level build file, they belong in the individual module build.gradle files

Paulo Merson
  • 13,270
  • 8
  • 79
  • 72
q...
  • 1,181
  • 10
  • 7
  • To confirm: does that mean that https://proandroiddev.com/how-to-setup-your-android-app-to-use-protobuf-96132340de5c should be using a `compile` and not a `classpath` ? – WillC Oct 13 '18 at 03:27
  • 2
    But why not place the application dependencies in the top level file itself if the project has just one module, like the typical android applications? – Harsha Mar 17 '20 at 14:49
  • @Harsha the gradle files are generated by Android Studio wizard. The creators of the wizard chose to make it possible to have multiple modules in the multi-project build. With that intent, it's logical not to assume the dependencies in the root project are not going to be shared in all of your modules. If you are sure you'll have only one module, you can put all of your dependencies inside `allprojects` block of the `root` `build.gradle` file. – Alexander Suraphel Nov 30 '21 at 10:38
63

I'm going to guess that you're referencing compile and classpath within the dependencies {} block. If that is so, those are dependency Configurations.

A configuration is simply a named set of dependencies.

The compile configuration is created by the Java plugin. The classpath configuration is commonly seen in the buildScript {} block where one needs to declare dependencies for the build.gradle, itself (for plugins, perhaps).

Jorge Gil
  • 4,265
  • 5
  • 38
  • 57
Eric Wendelin
  • 43,147
  • 9
  • 68
  • 92
  • Thanks, so for my main build.gradle I should not need to use classpath? – java123999 Dec 15 '15 at 22:01
  • @java123999 No, unless you use custom-written plugins – Eric Wendelin Dec 15 '15 at 22:26
  • @EricWendelin Where you say "within the dependencies {} block" do you mean "within the buildscript { dependencies{}} block"? (I'm not sure, just asking.) – Paulo Merson Sep 06 '18 at 18:04
  • 3
    A `dependencies {}` block can be declared both inside `buildscript {}` and outside of it. When inside, you use the `classpath` configuration for dependencies needed to compile the build script itself. – Eric Wendelin Sep 17 '18 at 23:07
28

If I understand correctly, you're confusing Project.dependencies script block with the Project.buildscript.dependencies script block (just like I did when I reached this question).

I'll try to answer this with what I found.

I think you should be already familiar with the Project.dependencies script block. In this block, we declare dependencies that are required by our source code. There are several ways to declare a dependency that we need for the project. See Gradle Tutorial: Dependency Types. I'll only mention the part that is the most relevant to this problem:

compile 'org.hibernate:hibernate-core:5.0.5.Final' is a module dependency declaration. The compile configuration (which is now deprecated by the implementation configuration.) is merely a keyword for Implementation only dependencies. It is not a keyword describing which type of dependency it is (by type here I'm following the three types defined in the tutorial, i.e. module, file, and project.)

In Gradle Tutorial: Organizing Build Logic it says:

If your build script needs to use external libraries, you can add them to the script’s classpath in the build script itself. You do this using the buildscript() method, passing in a closure which declares the build script classpath.

This is the same way you declare, for example, the Java compilation classpath. You can use any of the dependency types described in Dependency Types, except project dependencies.

Having declared the build script classpath, you can use the classes in your build script as you would any other classes on the classpath.

I hope things are getting clear to you now.

With classpath "com.android.tools.build:gradle:${Versions.android_gradle_plugin}" we're setting classpath method with com.android.tools.build:gradle:${Versions.android_gradle_plugin} which is a module dependency that is used by the build script itself rather than the source in your project.

On the other hand, with compile 'org.hibernate:hibernate-core:5.0.5.Final' we're declaring a module dependency required for your project with the compile configuration.

tl;dr: The classpath, compile, and implementation are all keywords that can be used against dependencies under different circumstances. The former is used when you want to pass in a dependency to the build script, and the latter is one of the configuration you may want to declare.

Teng-pao Yu
  • 1,313
  • 15
  • 30
  • 2
    Good answer. I have to add, that not only must we stare at the keywords themselves as what is nicely explained above, but in addition we also must take into consideration the artifact that is being requested because the keywords alone does not define the complete context. For example, `'org.projectlombok:lombok:1.18.4'` has no `classpath` association because it is a jar that is only needed during compile `javac` time but not needed on `java` runtime. Therefore, correct usage is an interplay of the defined keywords and the artifact. This means, one needs a-priori knowledge. – daparic Dec 14 '19 at 11:36
3

Android:

classpath in project build.gradle —— the implementation after classpath is only used by gradle it self, used in build script. So if i add the implementation (such as retrofit) in the project build.gradle classpath 'retrofit...', i can't get retrofit in my code!! Because —— my code can't see it, only the buildscript can see it.

implementation in app build.gradle —— add the implementation your code can use!!

JeckOnly
  • 347
  • 2
  • 10
  • 1
    i see a commet like this —— “But why not place the application dependencies in the top level file itself if the project has just one module, like the typical android applications? ” it will not work!! Reasom is above! – JeckOnly Oct 19 '21 at 13:27
  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/30119438) – user2807083 Oct 19 '21 at 13:45