Is there a way to tell Gradle to exclude all dependencies of a particular dependency, that would be pulled from a given repository ?
Removing that repository from the repositories list would not work, because I need that repository for other dependencies. But for one particular group, I want to exclude all dependencies that would come from that repository.
Something like :
dependencies {
compile <my_first_package>
compile('my_second_package') {
exclude repository.name:thirdPartyRepository
}
}
Looking at the source code, there are only two possibilities how to exclude a dependency and that is to exclude by module or a group. You can also mark a dependency not to fetch its transitive dependencies:
compile('my_second_package') {
transitive = false
}
But that's all, there seems to be no way to remove dependencies based on repository. You can force versions using a ResolutionStrategy, maybe take a look if something there helps your use case.
As a workaround, maybe you can repackage the wrong dependency under a different name or version. Or you could use the transitive = false and simply add all the transitive dependencies that you actually want as declared dependencies.
Related
I have to develop a module against a live system that has a lib folder.
In order to get all the dependencies, I need to add a dependency on that folder.
Then I add my own new dependencies using the gradle way compile ...
The problem is the system already contains some of the libs I add as dependencies or that are resolved as transitive dependencies.
I would like to be able to though each dependency and if I find one with the same name in the lib folder, remove it, so I can use the one resolved from the maven repository.
Any idea where I can insert that code, or if it is possible ?
** I guess one other option would be to copy them and filter by hand into a new lib folder, I am wondering if I can make something automatic that may take into account future upgrades
I have to develop a module against a live system that has a lib folder.
The problem is the system already contains some of the libs I add as dependencies or that are resolved as transitive dependencies.
The best way to manage this case is to avoid the lib folder and just move all these libraries/dependencies in a maven (private) repo.
In this way gradle will manage all nested dependencies avoiding to duplicate libraries with different versions.
I'm guessing you've got something like this
dependencies {
compile fileTree(dir: 'lib', include: '*.jar')
}
Unfortunately when you do this, the GAV (group, artifact, version) is not known to gradle. Each jar is simply a file without a GAV or any other metadata (eg transitive dependencies). None of these jars can participate in Gradle's dependency resolution.
If you want to put your jars in a local folder, I suggest you use the maven repository directory layout (eg /someFolder/$groupIdWithSlashes/$artifactId/$version/$artifactId-$version.$extension)
You could then specify the local folder as a maven repository
repositories {
maven {
url uri('mavenRepo')
}
}
dependencies {
compile 'group1:artifact1:1.0'
compile 'group2:artifact2:2.0'
}
Jars could then be stored as
mavenRepo/group1/artifact1/1.0/artifact1-1.0.jar
mavenRepo/group2/artifact2/2.0/artifact2-2.0.jar
Optionally, you might want to add poms with transitive dependencies etc at
mavenRepo/group1/artifact1/1.0/artifact1-1.0.pom
mavenRepo/group2/artifact2/2.0/artifact2-2.0.pom
More details on maven directory layout here
Adding another answer because you don't want to do it properly, you want a hack
You could do something like this:
def libJars = fileTree(dir: 'lib', include: '*.jar')
dependencies {
compile 'foo:bar:1.0'
compile project(':anotherProject')
compile libJars
}
libJars.files.each { File libJar ->
// assuming jars are named $module-$version.jar
Pattern pattern = Pattern.compile("(.+)-.+?\\.jar")
Matcher matcher = pattern.matcher(libJar.name)
if (!matcher.matches()) throw new RuntimeException("${libJar.name} does not match ${pattern.pattern()}")
String module = matcher.group(1)
// exclude other dependencies with the same module as this "libJar"
configurations.compile.exclude [module: module]
}
I have the following entry in my gradle file
dependencies {
compile 'org.A:A:1.0'
}
which downloads 'org.B:B:1.0' because that's it's dependency.(not mentioned explicitly in gradle)
What I want to use in my project is A* and B* which are shadows(changed namespace) of A and B respectively.
Now, I have specified the dependency for A* as
dependencies{
compile file('libs/A*.jar')
}
But, this one still downloads 'org.B:B:1.0'
How do I wire the gradle to use file('libs/B*.jar')?
The first solution that comes to mind is to exclude the transitive dependency of compile 'org.A:A:1.0'
This works like this:
dependencies {
compile('org.A:A:1.0') {
exclude 'org.B:B:1.0'
}
}
Have a look at the Gradle User Guide for more details on that subject.
As mentioned in the comments, file dependencies can't have transitive dependencies. So A*.jar either has the contents of the B.jar rolled into it somehow, or you have B.jar on the build path somewhere else.
File dependencies are generally a tool of last resort, they do not participate in conflict resolution; you need a dependency repository like maven or ivy for that.
I have a library, which I call core, which is a dependency of another project, called Museum. In core's build.gradle, I am using gson-fire, which is specified as a dependency in the following manner:
repositories {
maven { url 'https://raw.github.com/julman99/mvn-repo/master'}
}
...
dependencies {
compile 'com.github.julman99:gson-fire:0.11.0'
}
This works fine - core is compiled. When I go to use it in my Museum project, though, I get the following:
A problem occurred configuring project ':Museum'.
> Could not resolve all dependencies for configuration ':Museum:_debugCompile'.
> Could not find com.github.julman99:gson-fire:0.11.0.
Searched in the following locations:
file:/Users/jwir3/.m2/repository/com/github/julman99/gson-fire/0.11.0/gson-fire-0.11.0.pom
file:/Users/jwir3/.m2/repository/com/github/julman99/gson-fire/0.11.0/gson-fire-0.11.0.jar
http://download.crashlytics.com/maven/com/github/julman99/gson-fire/0.11.0/gson-fire-0.11.0.pom
http://download.crashlytics.com/maven/com/github/julman99/gson-fire/0.11.0/gson-fire-0.11.0.jar
https://repo1.maven.org/maven2/com/github/julman99/gson-fire/0.11.0/gson-fire-0.11.0.pom
https://repo1.maven.org/maven2/com/github/julman99/gson-fire/0.11.0/gson-fire-0.11.0.jar
Required by:
museum:Museum:unspecified > com.jwir3.core:core:1.4.0-SNAPSHOT
The build.gradle of Museum looks like the following:
dependencies {
compile ('com.thisclicks.core:core:' + project.CORE_LIB_VERSION+ '+#aar') {
transitive = true
}
}
Presumably, this is because the core library is specified as transient = true in the build.gradle of Museum, but it doesn't have the correct location to search for the Maven repository of gson-fire. Is there a way to make these search locations transient as well as the dependencies themselves?
Not automatically, no. Transitive dependencies do not bring in repository information, only the artifacts themselves. If you want this to work you'll have to add the repositories { } block from the core project to the Museum project.
Additionally, adding transitive = true is unnecessary in this case. This is the default anyway, and as explained above, is unrelated to this particular issue.
I've got a project that I want to use providedCompile with to avoid pulling it's libs. However, that prevents me from pulling in another project's libs that I do need. The docs say: If you don't want this transitive behavior, simply declare your provided dependencies, but it doesn't give an example of how to do this.
Here's basically what my dependencies look like:
dependencies {
compile(project(':common'))
providedCompile(project(':projA')) // <-- also depends on :common
}
My war file correctly excludes all of transitive libs from projA, but I need to trump that for the common.jar and I can't figure out how to make that happen. But the docs seem to indicate it's possible...
Edit: Here's a hacky configuration that seems to work. The combination of lines for "projA" gives me projA.jar as a dependency, but not its children. And since "common" is a compile dependency, but "projA" is only considered provided at runtime, I still get the common.jar due to the compile time dependency. I'm not sure it's supposed to work this way, but it generates the war I need.
dependencies {
compile(project(':projA')) { transitive = false }
providedRuntime(project(':projA')) { transitive = false }
compile(project(':common'))
}
If you don't want this transitive behavior, simply declare your provided dependencies
This means that if you don't want all dependencies of projA to be declared provided you need to list them as provided one by one.
From the Gradle 1.8 Userguide '26.4. Dependency management'
The War plugin adds two dependency configurations: providedCompile and
providedRuntime. Those configurations have the same scope as the
respective compile and runtime configurations, except that they are
not added to the WAR archive. It is important to note that those
provided configurations work transitively.
Let's say you add commons-httpclient:commons-httpclient:3.0 to any of
the provided configurations. This dependency has a dependency on
commons-codec. This means neither httpclient nor commons-codec is
added to your WAR, even if commons-codec were an explicit dependency
of your compile configuration. If you don't want this transitive
behavior, simply declare your provided dependencies like
commons-httpclient:commons-httpclient:3.0#jar.
There is another better solution that seems to be working. With transitive=false you exclude all the transitive dependencies that are then missing during compilation time and you have to declare all of them manually (again as provided) which is pain if they also include your desired library.
So for the providedCompile statement exclude not all transitive dependencies but only the one you want to include in war by separate compile statement.
Real example where I need the commons-codec included in the war file but that one is placed also in the keycloak-services and keycloak-model-jpa:
providedCompile ("org.keycloak:keycloak-model-jpa:6.0.1") {
exclude group: 'commons-codec', module: 'commons-codec'
}
providedCompile ("org.keycloak:keycloak-services:6.0.1") {
exclude group: 'commons-codec', module: 'commons-codec'
}
providedCompile "org.keycloak:keycloak-core:6.0.1"
providedCompile "org.keycloak:keycloak-server-spi:6.0.1"
providedCompile "org.keycloak:keycloak-server-spi-private:6.0.1"
compile "commons-codec:commons-codec:1.10"
I have a project in which I am using sl4j with log4j. I recently added a few new dependencies to my project, and one of these new dependencies that I added is including a transitive dependency to logback-classic, which includes another binding for sj4j.
I want to get rid of logback, but I have no clue which of my direct dependencies added the transitive dependency so that I can exclude it.
In maven I know how to get the entire graph of dependencies to determine which is the source of a transitive dependency, but I have no clue of how to do this with gradle.
Does anyone knows how to get the source dependency of a transitive dependency with gradle?
To show the whole dependency tree for each class path, use:
> gradle dependencies
If you are only interested in a particular class path, use (say):
> gradle dependencies --configuration compile
Use the -p option to run on a sub-project.
To show who pulls in a particular dependency onto a particular class path, and how any version conflicts were resolved, use (say):
> gradle dependencyInsight --dependency logback --configuration compile
Note that you can also exclude a dependency from a whole class path (or multiple). Usually this is more reliable than excluding a particular transitive dependency. For example:
configurations.all*.exclude module: "logback-classic"
An updated answer:
I used this code to resolve a dependency issue between logback and log4j:
configurations.all {
resolutionStrategy.dependencySubstitution {
substitute module('org.apache.logging.log4j:log4j-slf4j-impl') using module ('ch.qos.logback:logback-classic:1.2.3')
}
}
This solution finds any dependencies on log4j-slf4j-impl and instructs it to choose the one from logback (this is a spring app). This solution was surprisingly difficult to track down, but likely very useful in many situations.
Here's the gradle documentation on handling conflicting candidates.