Reputation: 23232
Having the following multi-module-setup:
multi
├── projA
│ └── build.gradle.kts
├── projB
│ └── build.gradle.kts
├── build.gradle.kts
└── settings.gradle.kts
with the following content (abbreviated):
settings.gradle.kts
rootProject.name = "multi"
include("projA", "projB")
projA\build.gradle.kts
dependencies {
implementation("important-library:1.0")
}
projB\build.gradle.kts
dependencies {
implementation(project(":projA"))
}
Why don't I have access to that importantlibrary:1.0
from projB
?
What works: if I have a class within projA
that uses the library, it works perfectly even if that class is called from a class within projB
(so indirect access works). Directly accessing any class from importantlibrary:1.0
within projB
doesn't work (unresolved reference).
What am I missing here? Or what needs to be set up so that it works?
Gradle version: 5.6.1
Upvotes: 14
Views: 23984
Reputation: 22867
There are 2 themes: transitivity of dependencies and /src
as dependency
We use api
so that the dependency can be exported to the higher hierarchy of modules.
dependencies {
api("group", "name", "version")
}
dependencies {
implementation(project(":domain"))
implementation(project(":library_base"))
}
We pass "default"
in the second parameter as configuration to be able to import the /src
from the lower hierarchy of modules.
dependencies {
implementation(project(":common", "default"))
}
To be able to access from :feature_a
to /src
of eg. :domain
we use "default"
as configuration and to be able to access the dependencies of :library_base
we make sure that they are defined with api
in that module so that they can be exported.
GL
Upvotes: 8
Reputation: 740
I think a good way to achieve what you want would be to use api
instead of implementation
. implementation
is meant to only keep the dependency inside the module, while api
is meant to export them along with the module. The dependencies for projA
would then become:
dependencies {
api("important-library:1.0")
}
This is the link to the official documentation: https://docs.gradle.org/current/userguide/java_library_plugin.html#sec:java_library_separation
Upvotes: 9
Reputation: 23232
I found lots of sources mentioning configuration
to handle how transitive dependencies are dealt with. Digging deeper I found that the default configuration should make the runtime
, runtimeOnly
and implementation
available to the referencing project.
Either I misinterpreted "default" here or you really need to call it using the "default"
-configuration explicitly. Declaring the dependency as follows in projB
, made the dependencies from projA
available to projB
as well:
implementation(project(":projA", "default"))
// or with named parameters:
implementation(project(path = ":projA", configuration = "default"))
Wondering whether this is/was really intended or whether that is rather an unfortunate default value for the configuration
-parameter of the project
-function.
Upvotes: 4