24

I have three gradle projects. Say ProjectA, ProjectB and ProjectC.

ProjectC is dependent on both ProjectA and ProjectB. While ProjectB is dependent on ProjectA.

So ProjectC's build.gradle has the following lines:

dependencies {
  implementation project(':ProjectA')
  implementation project(':ProjectB')
}

And ProjectB's build.gradle has the following:

dependencies {
  implementation project(':ProjectA')
}

My question is why do I need explicit implementation declaration for ProjectA in ProjectC's build file?

Since, I am adding ProjectB, shouldn't ProjectA be included automatically since ProjectB is dependent on ProjectA ?

In other words, why the following does not work for ProjectC ?

dependencies {
  implementation project(':ProjectB')
}

I am new to gradle and thus trying to understand how dependency management between Project's work.


Edit:

So I want to change ProjectB's build.gradle to below:

dependencies {
  api project(':ProjectA')
}

So that I can simplify ProjectC's build.gradle to:

dependencies {
  implementation project(':ProjectB')
}

However, I get the following error:

A problem occurred evaluating project ':ProjectB'.
> Could not find method api() for arguments [:ProjectA] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.

Am I missing something?

Vicky
  • 16,679
  • 54
  • 139
  • 232

2 Answers2

20

Because implementation is precisely for that: it tells that ProjectA is needed for the code of ProjectB to work (internally), but is not part of its API (i.e. you don't want clients of ProjectB to rely on the fact that it uses ProjectA internally).

If you want ProjectA to be part of the API of ProjectB, then use the api configuration rather than implementation.

See the guide for more details.

Opal
  • 81,889
  • 28
  • 189
  • 210
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • thanks. That helped. does gradle have "testApi" as well like "testCompile" and "testImplementation" ? – Vicky Mar 28 '19 at 07:10
  • Read the guide I linked to, and you'll know. – JB Nizet Mar 28 '19 at 07:22
  • I read the guide. And tried to do what I have described in the Edit section. However, I am getting the error mentioned. – Vicky Mar 28 '19 at 09:14
  • You need to apply the java-library plugin. – JB Nizet Mar 28 '19 at 10:15
  • 1
    this info is a bit obsolete: @Deprecated(message = "The apiElements configuration has been deprecated for dependency declaration. Please use the 'implementation' or 'compileOnly' configuration instead.") – tribbloid Jun 08 '20 at 02:57
6

Add

plugins {
    id 'java-library'
}

to the parent project build.gradle file, this will enable api modifier for the project, which tries to use it.

See: https://docs.gradle.org/current/userguide/java_library_plugin.html

Benas
  • 2,106
  • 2
  • 39
  • 66