The issue.
Gradle dependency management made so:
there is no easy way to check availability of dependencies updates (only using some third-party plugins like ben-manes/gradle-versions-plugin) and download updates replacing old versions;
dependencies artifacts are downloaded from remote repositories and then stored in gradle cache and reused in succeeding builds; but successful compilation of your project must not depend on having a connection to Internet, availability of remote repositories and existence of specific versions of dependencies in these repositories.
The goal.
download and store all dependencies artifacts in VCS;
manually check updates for these dependencies and download them.
My solution works for Gradle configuration using java or android plugins.
java plugin defines compile and testCompile configurations.
compile is for dependencies that are required to compile the production source of the project. testCompile is for dependencies that are required to compile the test source of the project.
Let's define our own configurations in build.gradle:
configurations {
download
testDownload
}
Next let's create directories:
libs/compile/downloaded is where download dependencies will be stored;
libs/testCompile/downloaded is where testDownload dependencies will be stored.
Next we define several tasks.
Delete dependencies from download configuration:
task cleanDownloadedDependencies(type: Delete) {
delete fileTree('libs/compile/downloaded')
}
Delete dependencies from testDownload configuration:
task cleanDownloadedTestDependencies(type: Delete) {
delete fileTree('libs/testCompile/downloaded')
}
Download dependencies from download configuration:
task downloadDependencies(type: Copy) {
from configurations.download
into "libs/compile/downloaded/"
}
Download dependencies from testDownload configuration:
task downloadTestDependencies(type: Copy) {
from configurations.testDownload
into "libs/testCompile/downloaded/"
}
Execute all above tasks to update dependencies:
task updateDependencies {
dependsOn cleanDownloadedDependencies, cleanDownloadedTestDependencies, downloadDependencies, downloadTestDependencies
}
Next we define our dependencies:
dependencies {
download(
'com.google.code.gson:gson:+',
'joda-time:joda-time:+',
)
testDownload(
'junit:junit:+'
)
And then we tell where compile and testCompile configurations should take dependencies used for compilation.
compile fileTree(dir: 'libs/compile', include: '**/*.jar')
testCompile fileTree(dir: 'libs/testCompile', include: '**/*.jar')
}
Now you can download or update already downloaded dependencies:
./gradlew updateDependencies
If you are using android plugin then you can also add androidTestDownload configuration for dependencies that are required for compilation and running tests on Android device. Also some dependencies can be provided as aar artifacts.
This is the example for Gradle configuration using android plugin:
...
repositories {
...
flatDir {
dirs 'libs/compile', 'libs/compile/downloaded',
'libs/testCompile', 'libs/testCompileDownloaded',
'libs/androidTestCompile', 'libs/androidTestCompile/downloaded'
}
}
configurations {
download
testDownload
androidTestDownload
}
android {
...
}
dependencies {
download(
'com.android.support:support-v4:+',
'com.android.support:appcompat-v7:+',
'com.google.android.gms:play-services-location:+',
'com.facebook.android:facebook-android-sdk:+',
'com.vk:androidsdk:+',
'com.crashlytics.sdk.android:crashlytics:+',
'oauth.signpost:signpost-core:+',
'oauth.signpost:signpost-commonshttp4:+',
'org.twitter4j:twitter4j-core:+',
'commons-io:commons-io:+',
'com.google.code.gson:gson:+',
'org.jdeferred:jdeferred-android-aar:+'
)
compile fileTree(dir: 'libs/compile', include: '**/*.jar')
testCompile fileTree(dir: 'libs/testCompile', include: '**/*.jar')
androidTestCompile fileTree(dir: 'libs/androidTestCompile', include: '**/*.jar')
}
task cleanDownloadedDependencies(type: Delete) {
delete fileTree('libs/compile/downloaded')
}
task cleanDownloadedTestDependencies(type: Delete) {
delete fileTree('libs/testCompile/downloaded')
}
task cleanDownloadedAndroidTestDependencies(type: Delete) {
delete fileTree('libs/androidTestCompile/downloaded')
}
task downloadDependencies(type: Copy) {
from configurations.download
into 'libs/compile/downloaded/'
}
task downloadTestDependencies(type: Copy) {
from configurations.testDownload
into 'libs/testCompile/downloaded/'
}
task downloadAndroidTestDependencies(type: Copy) {
from configurations.androidTestDownload
into 'libs/androidTestCompile/downloaded/'
}
task updateDependencies {
dependsOn cleanDownloadedDependencies, cleanDownloadedTestDependencies, cleanDownloadedAndroidTestDependencies, downloadDependencies, downloadTestDependencies, downloadAndroidTestDependencies
}
fileTree(dir: 'libs/compile', include: '**/*.aar')
.each { File file ->
dependencies.add("compile",
[name: file.name.lastIndexOf('.').with { it != -1 ? file.name[0..<it] : file.name }, ext: 'aar'])
}
fileTree(dir: 'libs/testCompile', include: '**/*.aar')
.each { File file ->
dependencies.add("testCompile",
[name: file.name.lastIndexOf('.').with { it != -1 ? file.name[0..<it] : file.name }, ext: 'aar'])
}
fileTree(dir: 'libs/androidTestCompile', include: '**/*.aar')
.each { File file ->
dependencies.add("androidTestCompile",
[name: file.name.lastIndexOf('.').with { it != -1 ? file.name[0..<it] : file.name }, ext: 'aar'])
}
For locking versions of downloaded dependencies (library/ etc versions to hard-coded versions) for making the builds reproducible, now Gradle 4.8 and onwards, we'll have inbuilt "dependency lock" support. This will help greatly to make builds reproducible if someone is using dynamic versions (M.m.p/i) Major.minor.patch/interimBranch etc (ex: 4.+ or 3.1.+) or version range for pulling artifacts from a binary repository tool (ex: Artifactory / Nexus).
Any Gradle user who is using Gradle version 4.8+ should start using this new feature.
https://docs.gradle.org/4.8/userguide/dependency_locking.html
For Gradle 4.8 Release Notes: https://docs.gradle.org/4.8/release-notes.html
In past, this dependency lock feature was provided to Gradle community and made available via a FOSS plugin available to Gradle from Netflix Nebula's https://github.com/nebula-plugins/gradle-dependency-lock-plugin and https://plugins.gradle.org/plugin/nebula.dependency-lock
Related
I'm using Gradle and I wonder how I can implement a run task so I can run the program from the command "./gradlew run". I have a project named "demo" and it have the task "application run". Then I created the project "HouseObserver" and it have not the task "application run".
My build.gradle file looks like this.
plugins {
// Apply the java-library plugin to add support for Java Library
id 'java-library'
}
repositories {
// Use jcenter for resolving dependencies.
// You can declare any Maven/Ivy/file repository here.
jcenter()
}
apply plugin: 'java'
task runApp(type: JavaExec) {
classpath = sourceSets.main.runtimeClasspath
main = 'HouseObserver.Main'
}
// Using and creating an Executable Jar
jar {
manifest {
attributes('Main-Class': 'HouseObserver.Main')
}
}
task runExecutableJar(type: JavaExec) {
// Executable jars can have only _one_ jar on the classpath.
classpath = files(tasks.jar)
// 'main' does not need to be specified
}
dependencies {
// This dependency is exported to consumers, that is to say found on their compile classpath.
api 'org.apache.commons:commons-math3:3.6.1'
// This dependency is used internally, and not exposed to consumers on their own compile classpath.
implementation 'com.google.guava:guava:28.0-jre'
// Use JUnit test framework
testImplementation 'junit:junit:4.12'
// Need at least basic JME
compile "org.jmonkeyengine:jme3-core:3.3.0-beta1"
compile "org.jmonkeyengine:jme3-desktop:3.3.0-beta1"
compile "org.jmonkeyengine:jme3-lwjgl3:3.3.0-beta1"
compile group: 'com.simsilica', name: 'lemur', version: '1.13.0'
compile group: 'com.simsilica', name: 'lemur-proto', version: '1.11.0'
// needed for the style language
runtime "org.codehaus.groovy:groovy-all:2.4.5"
// Standard utility stuff
compile 'com.google.guava:guava:19.0'
compile 'org.slf4j:slf4j-api:1.7.13'
runtime 'org.apache.logging.log4j:log4j-slf4j-impl:2.5'
runtime 'org.apache.logging.log4j:log4j-core:2.5'
}
I'm also trying the way to implement a task from a plugin.
plugins {
id 'application'
}
application {
mainClassName = 'my.packages.to.the.Main'
}
But nothing happens. Why?
EDIT:
Here is my latest gradle file.
plugins {
// Apply the java-library plugin to add support for Java Library
id 'java-library'
id 'application'
}
application {
mainClassName = 'HouseObserver.Main'
}
repositories {
// Use jcenter for resolving dependencies.
// You can declare any Maven/Ivy/file repository here.
jcenter()
}
dependencies {
// This dependency is exported to consumers, that is to say found on their compile classpath.
api 'org.apache.commons:commons-math3:3.6.1'
// This dependency is used internally, and not exposed to consumers on their own compile classpath.
implementation 'com.google.guava:guava:28.0-jre'
// Use JUnit test framework
testImplementation 'junit:junit:4.12'
// Need at least basic JME
compile "org.jmonkeyengine:jme3-core:3.3.0-beta1"
compile "org.jmonkeyengine:jme3-desktop:3.3.0-beta1"
compile "org.jmonkeyengine:jme3-lwjgl3:3.3.0-beta1"
compile group: 'com.simsilica', name: 'lemur', version: '1.13.0'
compile group: 'com.simsilica', name: 'lemur-proto', version: '1.11.0'
// needed for the style language
runtime "org.codehaus.groovy:groovy-all:2.4.5"
// Standard utility stuff
compile 'com.google.guava:guava:19.0'
compile 'org.slf4j:slf4j-api:1.7.13'
runtime 'org.apache.logging.log4j:log4j-slf4j-impl:2.5'
runtime 'org.apache.logging.log4j:log4j-core:2.5'
}
So, I'm trying to make a project using processing, and I intend to use gradle because I like how it simplifies the compiling of the process. In a class I was given a build.gradle that uses the deprecated function compile like this:
dependencies {
// Dependency on local binaries
compile fileTree(dir: 'libs', include: ['*.jar'])
}
jar {
manifest {
attributes "Main-Class": mainClassName
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
when I run this code, I get a warning from gradle telling me that this build is using some features that will be discontinued in gradle 7.0, I have confirmed that this features are the compile section of the build.gradle . So, I've been trying to include the processing core.jar in gradle using the newer functions of gradle, but i have been unable to succeed. So, how can I add the processing core.jar as a local library to my gradle project using the newest gradle?
thanks in advance and sorry for any spelling mistakes.
You need to stop using the compile configuration.
Instead you should use implementation for dependency declarations and runtimeClasspath for fat jar packaging.
Your example adapted:
dependencies {
// Dependency on local binaries
implementation fileTree(dir: 'libs', include: ['*.jar'])
}
jar {
manifest {
attributes "Main-Class": mainClassName
}
from {
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}
}
I have 3 modules: annotations, annotation_processor and app.
annotations/build.gradle
apply plugin: 'java-library'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
}
annotation_processor/build.gradle
apply plugin: 'java-library'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
api project(":annotations")
api "com.squareup:javapoet:1.11.1"
}
repositories {
mavenCentral()
}
sourceCompatibility = "1.8"
targetCompatibility = "1.8"
task deleteJar(type: Delete) {
delete 'libs/annotations.jar'
}
task createJar(type: Copy) {
from('build/intermediates/bundles/release/')
into('libs/')
include('classes.jar')
rename('classes.jar', 'annotations.jar')
}
createJar.dependsOn(deleteJar, build)
and app/build.gradle
dependencies {
...
implementation files('libs/annotation_processor.jar')
annotationProcessor files('libs/annotation_processor.jar')
...
}
When I run the project I get the following error.
error: package com.annotations does not exist
If I include annotations as a project the project I can skip this error but then I get.
Caused by: java.lang.NoClassDefFoundError: com/annotations/ProviderApi
at com.annotation_processor.ProviderAnnotationProcessor.getSupportedAnnotationTypes(ProviderAnnotationProcessor.java:45)
at org.gradle.api.internal.tasks.compile.processing.DelegatingProcessor.getSupportedAnnotationTypes(DelegatingProcessor.java:47)
at org.gradle.api.internal.tasks.compile.processing.NonIncrementalProcessor.getSupportedAnnotationTypes(NonIncrementalProcessor.java:33)
at org.gradle.api.internal.tasks.compile.processing.DelegatingProcessor.getSupportedAnnotationTypes(DelegatingProcessor.java:47)
at org.gradle.api.internal.tasks.compile.processing.TimeTrackingProcessor.access$101(TimeTrackingProcessor.java:37)
at org.gradle.api.internal.tasks.compile.processing.TimeTrackingProcessor$2.create(TimeTrackingProcessor.java:68)
at org.gradle.api.internal.tasks.compile.processing.TimeTrackingProcessor$2.create(TimeTrackingProcessor.java:65)
at org.gradle.api.internal.tasks.compile.processing.TimeTrackingProcessor.track(TimeTrackingProcessor.java:117)
at org.gradle.api.internal.tasks.compile.processing.TimeTrackingProcessor.getSupportedAnnotationTypes(TimeTrackingProcessor.java:65)
I can't access any of the dependencies (Java Poet and annotation module) from annotation_processor even though I have replaced implementation with api. Which should've expose the dependencies, but haven't.
I need the dependencies of the .jar file in the app module.
I'm new to Java Library and it may be I'm making a basic mistake, but can't seem to figure out, I've been at it for more than a day now.
You have to create a multi module gradle project.
I provide a small snippet of a multi module project.
project(':module1') {
dependencies {
compile project(':module-service-api')
compile 'org.apache.commons:commons-lang3:3.3.2'
compile 'log4j:log4j:1.2.17'
}
}
//module-app depends on module-service-impl
project(':module2') {
dependencies {
compile project(':module1')
}
For more details about multi module project, refer to the file build.gradle in the following project.
https://github.com/debjava/gradle-multi-module-project-1
If you want to create a fat jar or one jar, you have to include Gradle shadow plugin so that you can distribute the jar file along with other dependencies.
Refer below the link.
https://plugins.gradle.org/plugin/com.github.johnrengelman.shadow
If transitive libs aren't packaged with the JAR task:
By default, jar task in gradle builds an executable jar file from your project source files. It will not contain any transitive libs that are needed for your program.
To the contrary, Netbeans does package JAR dependencies or transitive libs. Rather than a fat JAR how does gradle include libs?
plugins {
id 'com.gradle.build-scan' version '1.8'
id 'java'
id 'application'
}
mainClassName = 'net.bounceme.dur.mbaas.json.Main'
buildScan {
licenseAgreementUrl = 'https://gradle.com/terms-of-service'
licenseAgree = 'yes'
}
repositories {
jcenter()
}
jar {
manifest {
attributes 'Main-Class': 'net.bounceme.dur.mbaas.json.Main'
}
}
dependencies {
//compile fileTree(dir: 'libs', include: ['*.jar'])
runtime group: 'com.google.firebase', name: 'firebase-admin', version: '5.2.0'
compile fileTree(dir: 'lib', include: '*.jar')
}
in relation to another question: what's the "way" to package libs with the JAR task which doesn't result in a "fat JAR"?
When using the application plugin, all libraries used by the application (own jar or transitive libraries) are put in a libs folder when packaged as an app. then these libs are referenced in the shell or batch script as classpath when launching the app.
The easiest way to create a fatjar in gradle, is to use the shadow plugin available via the plugin portal. see https://plugins.gradle.org/plugin/com.github.johnrengelman.plugin-shadow for details
how can I run my gradle project? Its a GUI application. I just want to run it so I can test it. Created a gradle project, copied my src file in and marked it as a source file (blue file). Now when I click run, the project runs all the gradle tasks but my application does not start. Here is my build.gradle file:
group '1'
version '1.0-SNAPSHOT'
apply plugin: 'groovy'
apply plugin: 'java'
apply plugin: 'application'
mainClassName = 'Main'
version = '1'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
jar {
baseName = 'JavaWinApp'
from files(sourceSets.main.output.classesDir)
from files(sourceSets.main.output.resourcesDir)
from { configurations.compile.collect { zipTree(it) } }
manifest {
attributes 'Implementation-Title': 'JavaWinApp'
attributes 'Implementation-Version': version
attributes 'Main-Class': 'Main'
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'org.codehaus.groovy:groovy-all:2.3.11'
testCompile group: 'junit', name: 'junit', version: '4.11'
compile 'com.intellij:forms_rt:6.0.5'
}
Can you see anything blatantly obvious that I should change or can you give me any pointers?
Please let me know if you require any other information and I will happily supply it. I am an utter noob with this. My only exposure to gradle is through Android Studio, there all just runs fine. Looks like I'm missing something obvious, but cannot seem to find it.
Thank you in advance
The gradle application plugin should add a run task to your build, that will start your application. To execute this task you will need to create a run configuration in IntelliJ for this task. See this documentation on how to create a gradle run/debug configuration.