This might be a silly question to ask but i m having some serious issues understanding gradle compile
-Lets say i have i have project structure like this
proj-- pro1--src
--build.gradle
-- pro2--src
--build.gradle
--build.gradle
--settings.gradle
and pro2 has 2 dependencies say log4j and pro1
now when i try to run gradle jar task it generates a build directory containing the jar "pro2.jar"
but it doesn't include the dependent classes of pro1
but in maven this works fine
please help me out
Thanks
I found the solution for above.
Turns out i was wrong. It did the same thing in maven also.
To include all the dependecies in maven an additional plugin is used .
"maven-dependency-plugin"
And in case of gradle we need to create a fatJar. Or for more customization we can create a ShadowJar
fatJar
jar{
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}
Related
I'm struggling with Gradle and the build configuration of the following project structure (pretty simple...):
/projA
/projB
/projC
projC using classes from projB.
In projA/settings.gradle:
include 'projB'
include 'projC'
In projC/build.gradle:
dependencies{
compile project(':projB')
}
In IntelliJ I have no problem of dependency resolution, but when I'm running a ./gradlew build in projA, I'm facing a compilation error:
ClassC: Unresolved reference: ClassB
(where ClassC is the class of projC which is failing on the use of ClassB which is a class from projB, obviously...)
Notice that the code is in Kotlin language, that I do not have any problem to run the app in IntelliJ (spring boot run), but any build with Gradle give me an error (both in Intellij and command line).
What am I missing?
Regards,
Adrien
It's a common Gradle idiom to have an additional top level directory for your rootProject. That's a special project that's the parent to all other projects in your build, in a multi-project build.
That's where your settings.gradle file goes:
include ':projA:projB'
include ':projA:projC'
Then, I'd recommend having projA as a subdirectory of your rootProject, so your hierarchy would look as follows:
/myProject
settings.gradle
/projA
build.gradle
/projB
build.gradle
/projC
build.gradle
Also, in projC/build.gradle, you'll want instead:
dependencies {
compile project(':projA:projB')
}
That should do it.
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
When writing a gradle plugin, is it possible to add dependencies to the compile and testCompile classpath for projects that apply the plugin?
If so, is there a simple example that you can reference?
As an example; let's say I wanted to write a plugin that, among other things, added the AWS Java API jars to a project i.e. I get the the jars on the classpath of the project where I apply the plugin allowing me to compile against them.
Thanks
I am not fully sure I understand the question but you can look at the gradle war plugin (https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/WarPlugin.java) which defines new tasks providedCompile which extends compile
Edit : making plugin with its dependencies
In your example, its totally possible that the plugin defines its own dependencies like in a normal build.gradle file
repositories {
mavenCentral()
}
dependencies {
compile "com.amazonaws:aws-java-sdk-ec2:1.10.2"
}
see for example the was plugin (https://github.com/classmethod-aws/gradle-aws-plugin/blob/develop/build.gradle) when you apply this plugin in your own build the aws dependencies will be downloaded and available to your build.
I would like to output a jar which internally contains my dependency jar but overrides a particular file in the dependency jar with my own. I am using gradle build. Can someone help me with this? The task which build jar for me:
jar {
archiveName "JarName-${version}.jar"
dependsOn configurations.runtime
from {
(configurations.runtime - configurations.provided).collect {
it.isDirectory() ? it : zipTree(it)
}
}
}
Well I actually stopped duplicating the file by including the following strategy:
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
It seems like my changes becomes a part of the output jar before they are being overridden by the file in my dependency jar. So, restricting duplicacy helped in resolving the issue.