In JAVA eclipse, the main class of the java project is defined as one of the class in the JAR of the 'lib' folder, and the root project (fooBar) is added as a dependency in the classpath.
This can be acheived in eclipse by simply adding the root project in the classpath. However, how do we add the dependency of the root project in gradle?
dependencies {
compile project(':fooBar');
}
> Project with path ':fooBar' could not be found in root project 'fooBar'.
The following is the project structure:
fooBar
-src/main/java
-src/test/java
-JRE System Library
-gradle
--wrapper
--launch.gradle
-lib
-build.gradle
-settings.gradle
-gradle-apps.settings
-gradle.properties
-gradlew
-gradlew.bat
I guess I got your point. First of all I have a doubt. Why are you adding
dependencies {
compile project(':fooBar');
}
this entry in build.gradle of fooBar project? This can cause cyclic dependency and results in build failure.
So I guess remove the above entry from build.gradle of fooBar project.
And please add the below code in your settings.gradle file:
rootProject.name = 'fooBar'
include ':fooBar'
Hope this will work.
As far as the project method is concerned, the root project has no name. So this is the syntax in the subproject's build.gradle:
dependencies {
compile project(':')
}
However, it is rarely a good idea to do this. It is too easy to end up with circular dependencies. Most multi-module projects have a separate "main" projects (called something like "main", "core" or "base"), and other modules can easily depend on that using compile project(':core') or whatever.
(Originally answered over here.)
Related
I am trying to figure out the proper way to declare a project dependency in gradle, i have this two subprojects:
A java app
apply plugin: 'java'
sourceSets {main {java {srcDirs = ['./']}}}
dependencies{compile project(':p2')}
jar {manifest.attributes(
'Class-Path': configurations.runtime.files.collect { it.name }.join(''),
'Main-Class': 'Main'
)
}
and a java library:
apply plugin: 'java-library'
sourceSets {main {java {srcDirs = ['./']}}
}
jar {
manifest.attributes(
'Class-Path': configurations.runtime.files.collect { it.name }.join(' ')
)
}
The root project is empty and the settings just include the subprojects.
The dependencies in the p1 project only tells that p2 must be built before p1, but what about configuring p2 as a lib for p1? Right now if a run p1 i got:
Exception in thread "main" java.lang.NoClassDefFoundError: StaticClass
Gradle build is fine:
C:\...>gradle build
BUILD SUCCESSFUL in 1s
4 actionable tasks: 4 up-to-date
I have to copy and paste p2.jar to the p1.jar directory for it to run properly, how can i get gradle to do it for me?
If you're trying to pack the classes from p2 into the p1 jar, try adding this to p1's build.gradle:
jar {
from project(':p2:').sourceSets.main.output
}
This is a bit unusual, though. Normally, if you've set up a separate library project, you pack it in a separate jar and add it to the classpath of dependent projects, so it's reusable.
Setting the Class-Path on the jar's manifest won't work the way you've written it. The manifest attribute interprets each entry as a file path relative to the working dir of the JVM, but you're just giving it the name of each jar, and Gradle doesn't do any copying or moving of files when setting up configuration classpaths. It's generally not a good idea to rely on the manifest to set the classpath, as it will only work if your jars are arranged on the filesystem exactly as as the manifest expects it. If this is really what you want, then you need to set up an 'installation' directory containing all the required jars arranged as expected. The Gradle Application Plugin can probably help you to achieve this, or something equivalent, but I've never used it.
Depending on your exact needs, you should have a look at the java-library-distribution plugin or the application plugin.
The first one will package a jar and its dependencies in an archive.
The second one will do the same and allow you to configure the main jar to be executable.
I'm asking you about a very basic question but I hope you can find the time to help me:
I'm trying to realise a java-project, that can spit out several different programs which partially have dependencies on other projects of mine.
In order to keep it simple, I want to have all the code in one project, run by Gradle, so if I make changes to a central library (the database connector for example) all the child-programs automatically recieve the changes.
An example could look like this:
project:
program_A
central_library
program_B
output:
program_A.jar (including central library)
program_B.jar (including central library)
Now I'm having serious troubles finding a correct buildscript for this and was wondering if someone here could help me out.
P.S. : Since I'm new to this, if I should realize this through different modules within the Gradleproject instead of different packages in the Gradleprojects sourcefile, feel free to tell me :)
One way to approach this is to have a root project, that holds the three other projects inside of it.
Specify the sub-projects inside its settings.gradle file:
rootProject.name = 'RootProject'
include 'program_A'
include 'central_library'
include 'program_B'
With this in place, program_a can depend on central_library by adding a dependency in its build.gradle:
dependencies {
compile project(':central_library')
}
I have a similar setup in one of my projects, although the "central library" is the root project and the submodules are test environments.
Create a root directory and put each library or program into its own sub-directory.
Create a gradle project in each subproject.
You can for example create a skeleton gradle project by running
gradle init --type=java-library
or
gradle init --type=java-application
Then in the root directory create a gradle multi-module project. Basically
run only
gradle init
and then create a settings.gradle and list all sub-projects there.
This is actually described very well in the gradle documentation:
https://guides.gradle.org/creating-multi-project-builds/
If I understand correctly, what you want to do is, when you change your local projects, you want other projects to see those details. For this you need to publish your projects to some kind of repo, like maven repo. You can do this from command line gradle publishToMavenLocal, or gradle build pTMl. You can also do this in build.gradle file with something like the following:
task sourceJar (type : Jar) {
classifier = constants.extSources
from sourceSets.main.allSource
}
publications {
mavenJava(MavenPublication) {
from components.java
artifact(sourceJar) {
classifier "sources" //classifier = constants.extSources
}
}
}
I have this project setup (in Android AIDE):
|---Project1
| |---App
| |---Lib
|
|---Project2
|---App
I want add project 1 Lib as dependency (or linked source, because i only need to access 1 class from the library) to Project2.
Project2 settings.gradle:
include ':Lib'
project(':Lib').projectDir = new File(settingsDir, '../Project1/Lib')
Project2 build.gradle:
compile project(':Lib')
I am getting the following error:
Project dependency 'Lib' not found.
Is there anything wrong with the folder path? I didn't find any good solution for this problem and i am not very familiar with gradle.
If i would instead link the library source folder to Project2 i tried to add the following lines to the build.gradle (under android section):
sourceSets {
main.java.srcDirs += '/../Project1/Lib/src/main/'
}
I could access the source if i used the full path down to the folder with the class file but with the problem that when i instantiated the class from the Lib in Project2 it gave me the error that the class was not found inside the package.
Do both projects need to have the same package names? What would be the best solution to manage this without having the Library as an standalone library?
After hours of researching and trying I hope that someone can explain how we can have Gradle including classes of one or more subproject into a specific jar.
Lets say we have just three modules
Core
App
Web
Obviously the App and Web project artifacts (jars) should contain all classes from the Core project.
Settings gradle:
rootProject.name = 'MyProject'
include 'MyProjectCore'
include 'MyProjectApp'
include 'MyProjectWeb'
MyProjectApp / MyProjectWeb:
...
dependencies {
...
compile project(':MyProjectCore')
}
The projects can be compiled but the output jars do not contain the core classes.
Okay finally I found a working solution even if it might not be the best.
For the App and Web projects I overwrite the jar task like this to add the source sets of the Core module.
jar {
from project.sourceSets.main.allSource
from project(":MyProjectCore").sourceSets.main.java.srcDirs
}
With this you can add all *.class files created in your subprojects into your jar automatically:
jar {
from {
subprojects.collect { it.sourceSets.main.output }
}
}
To make sure the .class are there, make sure the root project depends on the subprojects:
dependencies {
compile project(':mySubProject')
}
Currently, my build.gradle has a dependency on an external library built with Ant. To accomplish building the library, I followed the advice here and created a task which builds the external library, and copies it to the libs/ folder.
The task is called as part of a dependency:
build.gradle
dependencies {
compile fileTree('libs') {
include '*.jar'
builtBy 'myTask'
}
}
task myTask (type: GradleBuild) { GradleBuild antBuild ->
antBuild.buildFile('external-stub.gradle')
antBuild.tasks = ['clean', 'ivy.check', 'ivy.download', 'ivy.task', 'ivy',
'init', 'mergeCode', 'compile', 'jar', 'copyJarsToProject']
}
However, when the compile actually runs, the library I just built and copied in is not included in the dependencies, as evidenced by a whole lot of compilation errors.
Am I including the library the wrong way?
The full build.gradle and associated files are over at Github, and I've linked to the specific commit I'm having issues with: Source Repository
Alright, took me a while to get a build I was happy with. But, here's what was changed.
The actual build of the JAR was built using the same style, but moved to the external project (so that the main build project wasn't reaching across to it). I'll give an in-depth explanation below, but the commits are here and here. These are in order.
Basically, we export the jar as an artifact that other projects can depend on, rather than copying over the Jar ourselves. This way, the Ant build runs and other projects can see the Jar we just created. This is the end of the first commit. In the second commit, the task outputs are marked as needing to be regenerated only if the Jar does not exist. This was due to the fact that whenever I tried to build the app, it would take minutes to regen the Jar, and then have to repackage everything else as well. The code is below:
build.gradle External Project
configurations {
buildJSword
}
task doBuildJSword (type: GradleBuild) {
buildFile = 'jsword-stub.gradle'
tasks = ['clean', 'ivy.check', 'ivy.download', 'ivy.task', 'ivy',
'init', 'mergeCode', 'compile', 'jar'] //, 'copyJarsToMinimalBible']
ext.outputJar = file('distribution/jsword.jar')
outputs.upToDateWhen {
ext.outputJar.exists()
}
}
artifacts {
buildJSword(doBuildJSword.ext.outputJar) {
builtBy doBuildJSword
}
}
Then, the main project just has to add this project as a compile-time dependency:
build.gradle Main Project
compile project(path: ':jsword-minimalbible', configuration: 'buildJSword')
Hope this is helpful for anyone with a similar issue, let me know if you have questions!
Note: The build currently does not clean itself properly, so if you change any code in the external project, you need to delete the external Jar for everything to regenerate itself correctly.