extremely close to this SO post, and asked in comments, but left unclear there.
$ git clone https://github.com/k9mail/k-9.git
$ cd k-9/mail/protocols/smtp
$ ../../../gradlew dependencies | grep "4.7.1 (\*)\|4.7.1 (c)\|4.7.1 (n)" | sort -u
+--- com.jakewharton.timber:timber:4.7.1 (*)
+--- com.jakewharton.timber:timber:4.7.1 (n)
+--- com.jakewharton.timber:timber:{strictly 4.7.1} -> 4.7.1 (c)
What do (c) and (n) suffixes mean?
Sadly, the Gradle docs do not cover this topic so it is a bit confusing.
Issuing gradlew dependencies | tail shows a legend explaining the meaning of the printed suffixes.
(c) - dependency constraint
(*) - dependencies omitted (listed previously)
(n) - Not resolved (configuration is not meant to be resolved)
Constraints are not pulled in unless some other dependency pulls them in.
Transitive dependencies are listed only once and then omitted.
Declared just for holding/listing the dependency not resolving it to a graph. This is the case for configurations like implementation or api.
Related
Lets say I have 3 dependencies A, B and C. A depends on C V1.0 while B depends on C V2.0. If A uses C V2.0 then it throws an error and if B uses C V1.0 it will also thrown an error. These are both obviously unwanted behaviors. So I want a dependency tree that looks like this.
A
+--- C:1.0
B
+--- C:2.0
However, when I try to implement this with gradle I get this
A
+--- C:1.0 -> 2.0
B
+--- C:2.0
which means C:1.0 is not being used anywhere despite A requesting that version. How can I get gradle to not override the 1.0 version of C that A needs to work?
I use below config to force using old version of library_common in project my_library
my_library
dependencies{
compile("library_A")
compile("library_B")
compile("library_common:old_version"){
force = true
}
}
Library_common is resolved to old_version, which match our expectation
dependency tree
+---library_A
| +---library_common: new_version -> old_version
+---library_B
| +---library_common: old_version
+---library_common: old_version
Another Project my_application then have dependencies on my_library and a non_related_lib
my_application
dependencies{
compile("my_library")
compile("non_related_lib"){transitive = false}
}
Library_common is somehow resolved to new_version which causes the conflicts in my_library.
dependency tree
+---my_library
| +---library_A
| | +---library_common: new_version
| \---library_B
| | +---library_common: old_version -> new_version
| \---library_common: old_version -> new_version
+---non_related_lib
I know I can force library_common version again in my_application, but it seems not right, as my_library should handle this conflict by itself.
It seems to me Gradle ignores force=true constraint declared in a direct dependency. Could somebody help explain if this is the way Gradle works?
Also, another thought is to exclude library_common in library_A and library_B. Will need to test it. But this way may become complicated when library_common is included as a transitive dependency of library_A/B, and nested level is deep.
Could someone provide any suggestions on the best practice to downgrade a dependency in a library project?
Thank you!!
If you want to force an older version of a transitive dependency, you should use dependency constraints. If your libraries are all published using Gradle, the constraints are also packaged within the Gradle module metadata, which means they will be preserved whenever you add your libraries as dependencies to some other project.
This all means, your buildscript has to change to something like this:
// my_library
dependencies{
compile("library_A") // do not specify a version of library_A here
constraints {
compile("library_A:version") // specify a version of library_A here
compile("library_common") { // do not specify a version of library_common here
version {
strictly(old_version) // specify a version of library_common here
}
}
}
compile("library_B")
}
Our project worked until I tried to upgrade to Gradle 5. There the first thing it complained was that / isn't a good character for multi-projects, e.g. bla/blub isn't valid, so we changed this to bla:blub (even though the error message said : also isn't valid). But now we apparently have a circular dependency which didn't exist before with Gradle 4:
Circular dependency between the following tasks:
:lap:server:classes
\--- :lap:server:compileJava
+--- :lap:server:compileKotlin
| \--- :lap:server:jar
| +--- :lap:server:classes (*)
| +--- :lap:server:compileKotlin (*)
| \--- :lap:server:inspectClassesForKotlinIC
| \--- :lap:server:classes (*)
\--- :lap:server:jar (*)
Why could this be?
The problem was indeed with the : notation in our settings.gradle. Now that I've changed all the nested projects to - the problem is resolved.
More concretely, before we had something like:
include 'common/server',
'someproject/server',
'someproject/common',
'someproject/search',
...
which worked with gradle 4.
Then in Gradle 5 I've changed it to
include 'common:server',
'someproject:server',
'someproject:common',
'someproject:search',
...
which caused the issue, presumably because someproject:common depended on common:server or something of the likes.
Now that I've changed it to
include 'common-server'
project(':common-server').projectDir = file('common/server')
include 'someproject-server'
project(':someproject-server').projectDir = file('someproject/server')
include 'someproject-common'
project(':someproject-common').projectDir = file('someproject/common')
everything works like a charm. By the way, the error with the circular dependency is also reproducible in Gradle 4, it's just that there we still had the / notation.
For those of you who stumble on this question.
see : https://github.com/gradle/gradle/issues/847
in a multi project setup, a duplicate "shortname" will throw in a monkey wrench:
from the url above:
myApp
- client
- common
- server
- common
Even though it should be 2 distinct entries, the duplicate (shortname) of "common" is the issue/bug.
I ended up doing this: (my code is different names of course) (but the idea is)
myApp
- client
- clientcommon
- server
- servercommon
to disambiguate.
The url has some other ideas.
What I saw in my code was, the built jars looked something like this:
common-1.0-SNAPSHOT.jar
So that was what clued me in to "ahhh, maybe I have ambiguous issue with the shortname". And finally found that github-gradle link.
I have a multi-module Maven project (one level deep only). I like not to have to repeat the same things in all child projects, but how can I still do it (avoir repeating) when the parent project itself needs a different setting ?
The example I’m facing is when trying to produce a common folder for all artifacts and dependencies (but I can imagine other equivalent situations):
<properties>
<__.build.folder>../last_build</__.build.folder>
</properties>
Of course, this will lead to a situation where I have two last_build folder, one common to all child projects, one in the upper level folder.
How can I avoid that without having to duplicate the same setting in every child pom.xml ?
Can I use profiles ?
I don’t know, I’m new to Maven.
Thanks
Edit :
In this example, last_build is a subfolder of the folder containing the parent pom.xml. The child projects are all in other subfolders, from which last_build has to be addressed as "../last_build" - but not in the parent pom.xml !
|
*--rootFolder
| |
| *--last_build // aggregation folder
| |
| *--subProject1
| | |
| | *--pom.xml (../last_build)
| |
| *--subProject2
| | |
| | *--pom.xml (../last_build)
| |
| *--subProject3
| | |
| | *--pom.xml (../last_build)
| |
| *--pom.xml (last_build) // different here for the parent project
I don't think you're proceeding down a very useful path and I think that you may be confused about a few things.
First, at the highest level, your root or parent pom, there should be no project, no code, no resources, and no artifact, so there should also be no output or need for an output directory. All you should have at the highest level is the parent pom and subdirectories containing modules.
The next problem is that you think you need a common build folder. I am hard pushed to imagine a rational scenario where that would be necessary. The artifacts one typically builds in maven are self-contained jars/wars -- one per module, and these are cached in the local repo whenever you build through the install lifecycle. They can be used in situ from there.
I'm converting an existing java multimodule project to gradle. The dependencies are a bit complicated - in short, I have something along these lines:
Root project MainProject
+--- Project ':P1'
| \--- Project ':P1:P2'
\--- Project ':utilProject'
So, my mainProject depends on P1, which in turn depends on P2, and a utilProject.
The thing is, both P1 and P2 also depend on the utilProject.
In the build.gradle for each of these projects was just compiling the ':utilProject' (the project is always in the root, and the projects for the main one look as I wrote above):
dependencies {
compile project(':utilProject')
// compile some other dependencies
}
P1 and P2 are fine (compiling without errors), however the main project won't compile. I've tried changing the code in utilProject around, and found that while the utilProject itself does compile the latest changes, the the main project is blind to them.
Any ideas would be greatly appreciated.
/// Update - July 20th 2014
Forgot to mention the MainProject is an eclipse plugin, and so we use the wuff plugin to compile (though I'm not sure it's relevant).
Seems like there is no need for P2 - P1 won't compile either (previously it just didn't use that bit of updated code. My bad).
Also, while I wasn't able to reproduce, I was able to find a workaround - adding the latest utilProject.jar to the dependency list seems to do the trick. I'm not sure why it's necessary... any ideas? Note that I did have to add the P1.jar to the MainProject and so on to make things work, which seems to indicate something's wrong with the dependency list, but all the projects on that list compile just fine.