Adding jars to classpath using gradle - compilation

In gradle, is there a way to reference external jars. I have some external jars, sitting in another folder outside the project structure. Is there a way to add a reference to these jars in my build.gradle file, so that they are picked up during the compilation process?
Thanks
Edit:
I modified mu build.gradle with an allprojects task having the following 'sub-tasks(?)' as follows:
repositories{
flatDir name:'ExternalJars',dirs:'<path to the jars>'
dependencies{
compile: 'jarname:jarname:version'
}
}
This seems to make my build run just fine. Can someone shed some light on what exactly is happenning when I create the repository and specify the dependencies? - Thanks

The basic idea is that it looks for jar files in the root directory(s) you specified in flatDir that match [artifact]-[version].[ext] pattern.
Note: artifact group is ignored (so you can specify them as :jarname:version), and also all artifacts assumed to have no transitive dependencies.
By the way, another way to reference local jars is to create a local ivy repository. You'll need to use this if you want to declare transitive dependencies.

Related

Gradle filter duplicate dependencies after they have been resolved

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]
}

Gradle include jar produced by another project in war

Currently I have two projects with gradle build.gradle. The first is going to create a fat jar file, which I would like to include in a war file. I thought compiling it would be enough, but it doesn't seem to be ending up in the /lib directory of my war file. Anyone have thoughts I am quite new to gradle.
dependencies {
compile project(':JarProject')
providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
providedCompile 'org.apache.tomcat:tomcat-jsp-api:7.0.55'
}
war {
archiveName 'WarProject.war'
from 'JarProject/build/libs'
webXml = file('src/web.xml')
}
Does the second project war need to be in providedRuntime? Or should I publish the jar from the other project in the local maven repo and include it that way?
The War task essentially behaves like a CopyTask with regards to stuff it packs in the war, so the documentation on working with files is useful. In essence, I think you need something like (untested):
from fileTree('JarProject/build/libs') {
into("lib")
}
That being said, using mavenLocal() and publishing there also works, but it can lead to unexpected results when the war includes some old version from local, picking up the jar explicitly from the file system like above is better.
I think the elegant solution would be to use multi project builds and project level dependencies. You would have the two builds as separate projects of the same Gradle build and add the "jar project" as a regular compile dependency.
How have you declared the dependency? I assume you have a multi-project build with subprojects A and B, both using the War plugin. I made an experiment using Gradle 2.4 and if I declare B/build.gradle like this:
apply plugin: 'war'
dependencies {
compile project(':A')
}
then B.war contains WEB-INF/lib/A.jar. If you correctly follow conventions of Gradle War plugin (place web resources in A/src/main/webapp/ and code-related resources in A/src/main/resources/), then A.jar should contain what you want.
see this

Gradle: Include jar dependencies into ear/libs

I'm using Gradle to create an ear, but I'm having a hard time figuring out how to properly include dependencies in the lib folder.
I know that I can use
earlib project (group:name:version)
to include jars there. And that also those jars' compile dependencies are going to be added in the ear's lib folder.
My problem is that I also have jars that are listed in the ear's build.gradle as
deploy project (':jar-name')
How can I add their dependencies in the lib folder?
The only way I found is to add them as earlib or as dependencies of an earlib, but this forces me to write them twice and feels harder than it should be (with Maven you just need to specify your dependencies in the subprojects and they will be added in the ear\lib directory)
EDIT
Basically what I would like to end up with, is a transitive deploy configuration.

sbt PublishLocal to ivy2, for use by Gradle/Intellij

I publishLocal a jar with sbt. The jar is produced in a local file at a reasonable path based on build.sbt configuration as follows:
name := "Utilities One"
organization := "com.cosi"
scalaVersion := 2.11.6"
version := "0.2"
This creates the jar at: /home/bill/.ivy2/local/com.cosi/utilities-one_2.11/0.2/jars/utilities-one_2.11.jar
My build.gradle points to the ivy repo, and additionally names the dependency as follows:
dependencies {
compile 'com.cosi:utilities-one_2.11:0.2#jar'
}
This causes the gradle process to seek the jar at the path /home/bill/.ivy2/local/com.cosi/utilities-one_2.11/0.2/utilities-one_2.11-0.2.jar
I work around the incompatibility in path construction by manually creating a symbolic link, and the project builds (for Android) successfully.
But I would like to eliminate the need for the symbolic link by either adjusting the build.sbt or the gradle.sbt or both. Is it possible, and what would be best practice?
You can instead use sbt publishM2 and add mavenLocal() to your gradle repositories:
repositories {
mavenLocal()
}
publishM2 uses Maven repository layout and publishes to ~/.m2/repository which is the same directory used by mavenLocal().
Well, the simpler solution is embarrassingly obvious, but still unsatisfying:
compile files('/home/bill/.ivy2/local/com.cosi/utilities-one_2.11/0.2/jars/utilities-one_2.11.jar')
That is, merely change the Gradle reference type to file instead of ivy, since it is a local file. Maybe sbt and gradle and ivy weren't meant to play together.

How to define repositories for all subprojects in Gradle

I am writing Gradle scripts to build a lot of projects. They are using the same repositories so I would like to define repositories for all of my sub-projects instead of defining in each of them.
So I try to move the repositories definition from the build.gradle in an individual project into the build.gradle in their parent folder.
subprojects{
repositories{
mavenCentral()
flatDir{
name 'uploadRepository'
dirs '../../sharedlib'
}
}
}
However, the sub-projects can't find the repository definition at all. Moving other configurations in subprojects closure work. I've tried dependencies and properties configuration. They all work with no problem. I don't know why repositories work differently.
When Googling, I can't find any example of putting repositories inside subprojects, I suspect I am doing it the wrong way. Please tell me what's wrong.
Thanks!
I finally figured out what the problem was.
Originally, I missed the settings.gradle in the parent folder. (I don't know why dependencies configuration works even without this file)
After I put that in, the sub-projects could find the repositories, but the dependencies and an one property (sourceCompatibility=1.5) I defined in the parent project no longer works.
I have to move the apply plugin:'war' from the subproject's build.gradle to the parent's subprojects{...}
I figure that's because the dependencies and sourceCompatibility are things provided by the plugin. And somehow Gradle doesn't look into the subproject's script to find the plugin first.
Your repository declarations look fine, except that an upload repository isn't declared in the project.repositories block but inside the upload task (e.g. uploadArchives). The Gradle User Guide has the details.

Resources