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.
Related
I am trying out Gradle, and am wondering, what is supposed to happen to a project's dependencies after you run gradle build? For example, my sample projects don't run on the command line after they are built, because they are missing dependencies. They seem to compile fine, as gradle doesn't give me errors or warnings about finding the dependencies.
Gradle projects I've made in IntelliJ Idea have the same problem. They compile and run inside the IDE, but are missing dependencies and can't run on the command line.
So what is supposed to happen to the dependencies I declare in the build.gradle file? Shouldn't they be output somewhere together with my .class files? Otherwise, what is the point of gradle when I could manage this by editing my classpath?
Edit: Here is my build.gradle file:
apply plugin: 'java'
jar {
manifest {
attributes('Main-Class': 'Animals')
}
}
repositories {
flatDir{
dirs "D:\\libs\\gradleRepo"
}
}
dependencies {
compile name: "AnimalTypes-1.0-SNAPSHOT"
}
sourceSets{
main{
java {
srcDirs=['src']
}
}
}
Your Gradle build only takes care of the compile time and allows you to use the specified dependencies in your code (it adds them to the compile classpath). But it does not take care of the runtime. Once the JAR is build, you need to specify the runtime classpath and provide all required dependencies.
You may think, that this is bad or a disadvantage, but actually it is totally fine and intended, because if you build a Java library, you won't need to execute it, you just want to specify it as a dependency for another project. If you would distribute your library to a Maven repository, all dependencies from Maven repositories (module dependencies) would end up in a POM descriptor as transitive dependencies.
Now, if you want to build a runnable Java application, simply use the Gradle Application Plugin (apply plugin: 'application'), which will create a ZIP file containing the dependencies and start scripts providing your runtime classpath for execution.
Third-party plugins can also produce so-called fat JARs, which are JAR files with all dependencies included. It depends on your use case if you should use them, because often dependency management via repositories is the better way to go.
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
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.
gradle multiple build script dependencies
We am in the process from transacting my our build scripts from ant to gradle. The ant build is configured the old way without using ivy and getting the dependencies from a lib folder.
We have a number of custom ant tasks packaged in jar. To run the tasks in that jar we also need some other third parties dependencies from the same lib folder.
Being a complex build we cannot afford to move everything in one go and would rather move one bit at a time as we find some time to do it.
I was able to run those custom ant tasks from the gradle build but I am having problems accessing classes from or tasks jars in my gradle build scripts.
In the build script section we have a class path entry needed for artifactory plugin and I tried to add some more class path entries to make our local libs available.
buildscript {
….
dependencies {
// This dependency below is needed by artifactory plugin which we download
classpath "org.jfrog.buildinfo:build-info-extractor-gradle:3.0.1"
}
….
}
I tried lots of combinations but I could not get it to work. What we want is to be able to do something like below:
buildscript {
…
dependencies {
classpath {
["org.jfrog.buildinfo:build-info-extractor-gradle:3.0.1",
fileset(dir: "${antBuildDir}/customTasks", includes: 'myTasks.jar'),
fileset(dir: "${antBuildDir}/lib", includes: '*.jar')]
}
}
…
}
Any idea about how can I address this or any other suggestions if you think I am on the wrong path.
Thank you in advance.
Julian
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.