Gradle task to compile java files and resources to zip file - gradle

I'm new to Gradle and I have no past experience for Gradle builds. What I'm trying to achieve are compile Java classes, copy some files to build dir with some resource files and make a zip file of the whole directory.
Zip file contents
bin
----data
----java
----properties
----resources
----run.sh
----classes <---- Java compiles classes here!
lib
----sqlite-jdbc-3.23.1.jar
properties
----MANIFEST.MF
I tried to Gradle build for Java but it makes too much tasks for this and I think it's overkill for my purposes. I want to write simple compile and copy task for this. Or if I need to use all java build tasks, how can I edit those task operations?

I think you should use both Java and Distribution plugins, that will help you to create a simple build script. Java plugin will bring you some tasks that you might not need in you case, but it still worth using it instead of creating your own task for source compilation.
An example of script you could use as a starter:
plugins {
id 'java'
id 'distribution'
}
// Java plugin configuration
// ---------------------------------------------------
sourceCompatibility = 1.8
targetCompatibility = 1.8
repositories {
jcenter()
}
dependencies {
compile group: 'org.xerial', name: 'sqlite-jdbc', version: '3.23.1'
}
// Distribution plugin configuration
// ------------------------------------------------------
distributions {
main {
baseName = 'myDist'
contents {
// 1. by default, content under /src/main/dist will be automatically included in the target dist zip
// 2. include compiled classes output dir into /bin/classes
from(project.sourceSets.main.output.classesDir) {
into('bin/classes/')
}
// 3. include all dependent jars into /libs
from(configurations.compile) {
into('libs/')
}
// 4. other resources to include in the target zip
// ...
}
}
}
// Make distZip task depend on compileJava task
distZip {
dependsOn compileJava
// EDIT : change target file path
eachFile { file ->
String path = file.relativePath
String newPath = path.substring(path.indexOf("/")+1,path.length())
println "Changed path to file from $path to $newPath"
file.setPath(newPath)
}
}
This script assumes that you follow standard directory layout in your project, for your source code and resources ( src/main/java/ , src/main/dist/ , ..), else you will have to adapt the script.

Related

Compile task is running successful but not generating any class files

I want to implement a gradle build script which compiles some java classes and copy it to to a tomcat directory. I dont want to use Gradle Java plugin since it does many things which are not relevant. I want to define my own compile & deploy tasks which does it. I have implemented it as below -
task compile (type: JavaCompile) {
source = fileTree('$srcdir')
destinationDir = file('$builddir')
classpath = files('lib')
sourceCompatibility = '1.8'
}
task deploy (type: Copy) {
dependsOn compile
from fileTree('build') {
include fileTree('classes')
}
from fileTree('lib') {
include '*'
}
into '${tomcathome}//${projectname}'
}
I have not touched deploy task yet. When i am running compile tasks it is running successful but not generating any class files. I am expecting it to be generated under /build directory.
Please suggest.
Thanks
To summarise the comments in the answer, you need to use GString like #lu.koerfer stated
this way it will always be interpreted as the literal location (a subfolder called $srcdir in this case)
This is needed when using variables inside a string, if don't need to use it in a string then don't (then you don't need a dollar sign).
Not sure how your variables are defined but for build and source directories you should ideally use Gradle provided variables
buildDir to point the build directory
sourceSets.main.java.getSrcDirs() to get source directories (depending on the project structure)
or sourceSets.main.java.srcDirs but note this is going to return the collection of your source directories, depending how you specified your sourceSets, or if you haven't at all then by default is going to return a maven convention structure src/main/java
For some global variables please read about Ext variables

Generate CLASSPATH from all multiproject gradle build dependencies

We're using an external testing tool (Squish) which runs after our main gradle build. This requires visibility of classes under test. Currently the CLASSPATH environment variable is built from various bash scripts and other string manipulation. I'm aiming to get gradle to do this automagically.
Since the build is done on a very slow source control system (clearcase) it is preferable for the tests to be run against the class files/JARs as left by the build rather than extra copies / compression into a single JAR etc.
The classpath needs to contain
Generated JAR files, typically in build/libs/project-x.jar
Test classes typically build/classes/test
Test resources typically build/resources/test
Any 3rd party jars any of the child projects depend upon, log4j, spring etc.
It's a complex multiproject build, but I've simplified to following example with parent and two children.
Parent settings.gradle
include ':child1'
include ':child2'
Parent build.gradle
allprojects {
apply plugin: 'java'
repositories {
mavenCentral()
}
}
Child 1 build.gradle
dependencies {
compile 'org.springframework:spring-context:4.1.2.RELEASE'
compile 'org.springframework:spring-beans:4.1.2.RELEASE'
}
Child 2 build.gradle
dependencies {
project (":child1")
}
What I've got so far. Is this the right approach? Can it be simplified or completely rewritten in a better way?
task createSquishClasspath << {
def paths = new LinkedHashSet()
paths.addAll(subprojects.configurations.compile.resolvedConfiguration.resolvedArtifacts.file.flatten())
paths.addAll(subprojects.jar.outputs.files.asPath)
paths.addAll(subprojects.sourceSets.test.output.resourcesDir)
paths.addAll(subprojects.sourceSets.test.output.classesDir)
paths.each {
println "${it}"
}
println paths.join(File.pathSeparator)
}
Output
C:\so-question\Parent\local-repo\spring\spring-context-4.1.2.RELEASE.jar
C:\so-question\Parent\local-repo\spring\spring-beans-4.1.2.RELEASE.jar
C:\so-question\Parent\child1\build\libs\child1.jar
C:\so-question\Parent\child2\build\libs\child2.jar
C:\so-question\Parent\child1\build\resources\test
C:\so-question\Parent\child2\build\resources\test
C:\so-question\Parent\child1\build\classes\test
C:\so-question\Parent\child2\build\classes\test
In summary the best answer so far is to join all the paths from the projects dependencies and all the test.output.resourcesDir and test.output.classesDir
task createSquishClasspath << {
def paths = new LinkedHashSet()
paths.addAll(subprojects.configurations.compile.resolvedConfiguration.resolvedArtifacts.file.flatten())
paths.addAll(subprojects.jar.outputs.files.asPath)
paths.addAll(subprojects.sourceSets.test.output.resourcesDir)
paths.addAll(subprojects.sourceSets.test.output.classesDir)
paths.each {
println "${it}"
}
println paths.join(File.pathSeparator)
}

jacoco+gradle taskdef A class needed by class org.jacoco.ant.InstrumentTask canno t be found

I'm trying to get jacoco+gradle work together. Looking at this forum it seems some people have successfully done that. But when I tried I got a strange exception.
What I did:
1.Downloaded gradle 2.2.1 and configured env variables, etc.
2.Downloaded jacoco 0.7.1 from http://www.eclemma.org/jacoco/
3.added:
apply plugin: 'jacoco'
and
buildTypes {
debug
{
testCoverageEnabled true
...
in the build.gradle
4.run gradle build
5.I got an error saying the jacoco agent jar cannot be found, etc. Error message showed it tried to search files under C:\Program Files (x86)\Android\android-sdk\extras\android\m2repository... etc.
6.I manually unzipped the jacoco jar files and put them in the place where the error message mentioned and the error message disappeared.
7.Then I ran gradle build. I got the following new error when running the built-in instrumentDebug task:
Caused by: : taskdef A class needed by class org.jacoco.ant.InstrumentTask cannot be found: org/jacoco/core/runtime/IExecutionDataAccessorGenerator using the classloader AntClassLoader[C:\Program Files (x86)\Android\android-sdk\extras\android\m2repository\org\jacoco\org.jacoco.ant\0.7.1.201405082137\org.jacoco.ant-0.7.1.201405082137.jar]
at org.apache.tools.ant.taskdefs.Definer.addDefinition(Definer.java:612)
at org.apache.tools.ant.taskdefs.Definer.execute(Definer.java:237)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:292)
at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
at org.gradle.api.internal.project.ant.BasicAntBuilder.nodeCompleted(BasicAntBuilder.java:77)
at org.gradle.api.internal.project.ant.BasicAntBuilder.doInvokeMethod(BasicAntBuilder.java:92)
at com.android.build.gradle.internal.coverage.JacocoInstrumentTask.instrument(JacocoInstrumentask.groovy:51)
at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:63)
at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.doExecute(AnnotationProcessingTaskFactory.java:218)
at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:211)
Caused by: java.lang.ClassNotFoundException:
at org.jacoco.core.runtime.IExecutionDataAccessorGenerator
at org.apache.tools.ant.AntClassLoader.findClassInComponents(AntClassLoader.java:1366)
at org.apache.tools.ant.AntClassLoader.findClass(AntClassLoader.java:1315)
at org.apache.tools.ant.AntClassLoader.loadClass(AntClassLoader.java:1068)...
When I used process monitor (My dev machine is Win 7), I saw there was no access to org.jacoco.core-0.7.1.201405082137.jar,which the org.jacoco.ant.InstrumentTask class resides in. So I think the gradle did not pass the file path to org.apache.tools.ant.AntClassLoader correctly.
I have tried below ways but none of them worked:
Add all jacoco jar files to CLASSPATH environment variable.
Add the jacoco jar files to ant libs, gradle libs,gradle libs/plugins, folder.
Look at source code of gradle 2.2.1. Clueless at this moment...
Does anyone know how to resolve this problem?
Thanks in advance!
Edit:
The main purpose is to:
1. Let jacoco build an instrumented apk file
2. Manually test the apk file (Not auto test)
3. Let jacoco generate coverage report
Update:
I just found when executing InstrumentDebug task, the gradle starts a new process with below command:
"C:\Program Files\Java\jdk1.8.0_25\bin\java.exe" -XX:MaxPermSize=512m -Xmx2048m -Dfile.encoding=UTF-8 -Duser.country=CN -Duser.language=zh -Duser.variant -cp D:\gradle-2.2.1\gradle-2.2.1\lib\gradle-launcher-2.2.1.jar org.gradle.launcher.daemon.bootstrap.GradleDaemon 2.2.1 D:\gradle-2.2.1\gradle-2.2.1\daemon 120000 744501ac-32c1-4930-82bd-59e0a9e2b92d -XX:MaxPermSize=512m -Xmx2048m -Dfile.encoding=UTF-8 -Duser.country=CN -Duser.language=zh -Duser.variant
As you can see the class path is hard coded, which overwrites what defined in environment variable. So the required core lib of jacoco could not be found and thus caused this problem. I'm now trying to see where this process is started and whether there is a way to change the -cp option.
Update2:
I finally found this process is started by gradle-launcher-2.2.1.jar. See below code. I'm now trying to see whether it's possible to change DefaultModuleRegistry and make registry.getGradleHome() == null. In the meantime could anyone who has successfully used jacoco+gradle tell me which version of gradle are you using?
public DaemonStartupInfo startDaemon()
{
DefaultModuleRegistry registry = new DefaultModuleRegistry();
Set<File> bootstrapClasspath = new LinkedHashSet();
bootstrapClasspath.addAll(registry.getModule("gradle-launcher").getImplementationClasspath().getAsFiles());
if (registry.getGradleHome() == null)
{
bootstrapClasspath.addAll(registry.getFullClasspath());
}
if (bootstrapClasspath.isEmpty()) {
throw new IllegalStateException("Unable to construct a bootstrap classpath when starting the daemon");
}
new JvmVersionValidator().validate(this.daemonParameters);
List<String> daemonArgs = new ArrayList();
daemonArgs.add(this.daemonParameters.getEffectiveJavaExecutable());
List<String> daemonOpts = this.daemonParameters.getEffectiveJvmArgs();
LOGGER.debug("Using daemon opts: {}", daemonOpts);
daemonArgs.addAll(daemonOpts);
daemonArgs.add("-cp");
daemonArgs.add(CollectionUtils.join(File.pathSeparator, bootstrapClasspath));
daemonArgs.add(GradleDaemon.class.getName());
daemonArgs.add(GradleVersion.current().getVersion());
daemonArgs.add(this.daemonDir.getBaseDir().getAbsolutePath());
daemonArgs.add(String.valueOf(this.daemonParameters.getIdleTimeout()));
daemonArgs.add(this.daemonParameters.getUid());
...
}
See if this helps.
I'm not using Gradle 2.2.1 but this is what I have in my Global Gradle file (i.e. a file in $GRADLE_HOME/init.d level file). File name can be anything with .gradle extension.
allprojects {
apply plugin: 'java'
apply plugin: 'pmd'
apply plugin: 'findbugs'
apply plugin: 'checkstyle'
apply plugin: 'jacoco'
//NOTE1: The following soureSet section is NOT required, if your folder structure follows what Gradle says where your main source should reside, where test (Unit tests) should reside, and where other like integrationTest (integration tests code reside). If your project structure doesn't follow the Gradle defined structure, then you can define that as my source code is not under src/main/java but is under src/java. The use of "sourceSet" section in this global file is only helping to use some conventional values in this global level file for ex: see integrationTest task and jacocoTestReport task below (you can't use those values if sourceSet is NOT defined in this file and if your project doesn't following the Gradle defined structure).
//NOTE2: Here in the global level Gradle file, I'm using values for sources for main, test, integrationTest etc as "dont_change_me" as I don't know what all projects (which will use this Gradle's global level file), will have what source code structure. The main / actual values of the sources for main, test and integrationTest task MUST be defined in the PROJECT's build.gradle file in sourceSets { main { java { srcDir 'src/java' } } } way.
sourceSets {
main {
java {
srcDir 'dont_change_me'
}
resources {
srcDir 'dont_change_me'
}
}
test {
java {
srcDir 'dont_change_me'
}
resources {
srcDir 'dont_change_me'
}
}
integrationTest {
java {
srcDir 'dont_change_me'
}
resources {
srcDir 'dont_change_me'
}
}
acceptanceTest {
java {
srcDir 'dont_change_me'
}
resources {
srcDir 'dont_change_me'
}
}
}
//...more code here
//...more code here
// The following is necessary to get code coverage info out. Compile with debug mode.
tasks.withType(Compile) {
options.debug = true
options.compilerArgs = ["-g"]
}
jacoco {
//toolVersion = "0.6.2.201302030002"
//toolVersion = "0.7.0.201403182114"
//toolVersion = "0.7.1.201404171759"
//This is latest than above, you may find later versions in online Maven repository.
toolVersion = "0.7.2.201409121644"
//OK I don't need the following folder to be created as I'll define my own.
// reportsDir = file("$buildDir/customJacocoReportDir")
}
//The following section is for UNIT tests (as build task in Gradle calls test task for free)
test {
maxParallelForks = 5
forkEvery = 50
ignoreFailures = true
// I want my reports (html) files to be created in a user defined folder UT(Unit test in build/reports/UT folder) and xml files (in user defined folder UT folder) under build/test-results/UT folder.
testReportDir = file("$buildDir/reports/tests/UT")
testResultsDir = file("$buildDir/test-results/UT")
//Following jacoco session will RUN in GRADLE's JVM session (during build / test time). This is different JVM than what many think of a runtime/Tomcat JVM session where we run a .war/.ear/etc file of an app to run that app and if you want to get code coverage of your main source code using non-unit tests from a Tomcat JVM, then see next task (integrationTest) as the following jacoco section in this "test" task is just for UNIT tests running in Gradle JVM session on a machine.
jacoco {
//NOTE: The following vars works ONLY with Gradle <= 1.6 version
// Create jacoco .exec file for Unit test in a user defined location
destPath = file("$buildDir/jacoco/UT/jacocoUT.exec")
//The following line is not that usesful acc. to my experience so commented it.
//classDumpPath = file("$buildDir/jacoco/UT/classpathdumps")
//NOTE: Following vars works only with versions >= 1.7 version of Gradle
//destinationFile = file("$buildDir/jacoco/UT/jacocoUT.exec")
// classDumpFile = file("$buildDir/jacoco/UT/classpathdumps")
}
}
task integrationTest( type: Test) {
//Always run tests
outputs.upToDateWhen { false }
//Ignore the failures if any during tests and don't mark the Gradle task as failed.
//You can comment this line if you want your gradle task to fail as soon as it finds any failing tests.
ignoreFailures = true
//This is telling Gradle that where it'll find class files from integration tests source code
testClassesDir = sourceSets.integrationTest.output.classesDir
//What path to use in classpath for integration tests
classpath = sourceSets.integrationTest.runtimeClasspath
//My custom location where I want my html reports files and xml result times of integration tests
testReportDir = file("$buildDir/reports/tests/IT")
testResultsDir = file("$buildDir/test-results/IT")
//Jacoco section in IT tests is NOT required here. Why as it'll never generage a coverage report this way as this way of using jacoco section in integrationTest task is telling Gradle to use jacoco in Gradle JVM and for getting code coverage you have to run jacoco/jacocoagent.jar in Target JVM (which is Tomcat or similar) by introducing jacocoagent.jar and other parameters for jacoco to Tomcat using one of Tomcat's -Dxxx option (see Jacoco help on how to do this). As the following is not required, I'm commenting the following jacoco code(otherwise if used, it'll always give you 0% coverage).
//jacoco {
//This works with 1.6
// destPath = file("$buildDir/jacoco/IT/jacocoIT.exec")
// classDumpPath = file("$buildDir/jacoco/IT/classpathdumps")
//Following works only with versions >= 1.7 version of Gradle
//destinationFile = file("$buildDir/jacoco/IT/jacocoIT.exec")
// classDumpFile = file("$buildDir/jacoco/IT/classpathdumps")
//}
}
jacocoTestReport {
group = "Reporting"
description = "Generate Jacoco coverage reports after running tests."
ignoreFailures = true
//Use any .exec file found before generating coverage report i.e. it'll give you combined coverage report if you have both jacocoUT.exec and jacocoIT.exec or other .exec files in build/jacoco/xx folders.
executionData = fileTree(dir: 'build/jacoco', include: '**/*.exec')
//executionData = files('build/jacoco/UT/jacocoUT.exec', 'build/jacoco/IT/jacocoIT.exec')
//executionData = files(['build/jacoco/UT/jacocoUT.exec', 'build/jacoco/IT/jacocoIT.exec'])
reports {
xml{
enabled true
//Following value is a file
destination "${buildDir}/reports/jacoco/xml/jacoco.xml"
}
csv.enabled false
html{
enabled true
//Following value is a folder
destination "${buildDir}/reports/jacoco/html"
}
}
//The following is an example of using Gradle conventional way of saying where is my main source code directory
//sourceDirectories = files(sourceSets.main.allJava.srcDirs)
sourceDirectories = files(['src/java', 'src/groovy'])
classDirectories = files('build/classes/main')
}
}
In Project's build.gradle, you define sourceSets section (with actual values) if your project structure if different than what Gradle says it should be. You define dependencies (i.e. for compile you need this .jar, for test or integrationTest, you need this .jar or .class from main/test etc).
Then, if you run gradle clean build, you'll get jacoco code coverage data for UT(Unit tests) under build/jacoco/UT folder in the form of an .exec file. Under build/reports/... html folder, you'll find jacoco main index.html which will show you the code coverage report.
If you want code coverage report from non-Unit tests (i.e. Integration tests etc), then attach the following parameter to the target JVM. I use Tomcat, so I'm attaching this, where testType is a variable which I use to find/tell whether I'm running IT(Integration Tests), AT (Acceptance Tests) or ST (Selenium GUI tests).
export PROJ_EXTRA_JVM_OPTS="-javaagent:tomcat/jacocoagent.jar=destfile=build/jacoco/${testType}/jacoco${testType}.exec,append=false"
and in startTomcat.sh script which I use, you'll notice I'm using the above variable and passing it to Tomcat's JVM as that's the JVM which is running my project's main .war/.ear file which has the main source code class files against which I want my code covreage data using Integration/Acceptance/other non-UNIT type tests:
## Tomcat command - JDK 1.6/Tomcat 6.0
TOMCAT_CMD="$JAVA_HOME/bin/java $TOMCAT_JVM_ARGS \
$OPTIT_JVM_ARGS \
$JPROF_JVM_ARGS \
$PROJ_EXTRA_JVM_OPTS \
org.apache.catalina.startup.Bootstrap $TOMCAT_CFG_FILE_ARGS start"
The above variable needs to be there in the Tomcat start script i.e. when Tomcat starts, it should get the above variable in its JVM session. Once this is done, you have to run "gradle integrationTest" then stop your Tomcat session(only then it'll flush the code coverage data to jacocoIT.exec file) and then if you run "gradle jacocoTestReport", it'll read the jacocoIT.exec file and genreate jacoco code coverage report for your main source code which your Integration/Acceptance/Selenium Tests tried to cover.

Delombok using Gradle

As part of our build process we analyse our source code with SonarQube.
One problem with this is that we use Lombok annotations and SonarQube is not handling this very well -- our code needs to be 'delombok'ed.
Delomboked source removed the annotations and replaces the source file with the final code used by the compiler.
This can be done in gradle (see here).
Well, in part. Typically an Ant task can be used to delombok source. Code sample below:-
task delombok {
// delombok task may depend on other projects already being compiled
dependsOn configurations.compile.getTaskDependencyFromProjectDependency(true, "compileJava")
// Set up incremental build, must be made in the configuration phase (not doLast)
inputs.files file(srcJava)
outputs.dir file(srcDelomboked)
doLast {
FileCollection collection = files(configurations.compile)
FileCollection sumTree = collection + fileTree(dir: 'bin')
ant.taskdef(name: 'delombok', classname: 'lombok.delombok.ant.DelombokTask', classpath: configurations.compile.asPath)
ant.delombok(from:srcJava, to:srcDelomboked, classpath: sumTree.asPath)
}
}
The problem I have with this is that I believe I would need a pre-configured ant system (I've yet to get this working).
Another approach would be to use a Maven lombok:delombok plugin (see here). However I don't know how to do this and if this would also require a pre-configured environment.
I'm not sure which is the best approach. An approach that does not require a pre-configured build system and can work fully from gradle/gradlew would be preferrable.
The ultimate aim would to have a 'delombok' project task which would essentially perform the following:
java -jar lombok.jar delombok src -d src-delomboked
edit
So i've pretty much got this to work with roughly this snippet:-
dependencies {
compile 'org.projectlombok:lombok:1.14.2'
}
task delombok {
description 'Delomboks the entire source code tree'
def srcDelomboked = 'build/src-delomboked'
def srcJava = 'src'
inputs.files file( srcJava )
outputs.dir file( srcDelomboked )
doLast {
def collection = files( configurations.compile + configurations.testCompile )
def sumTree = collection + fileTree( dir: 'bin' )
ant.taskdef( name: 'delombok', classname: 'lombok.delombok.ant.DelombokTask',
classpath: configurations.compile.asPath +
configurations.testCompile.asPath )
ant.delombok( from:srcJava, to:srcDelomboked, classpath: sumTree.asPath )
// Replace current src directory with delomboked source
copy {
from srcDelomboked
into srcJava
}
}
}
This first bit ensures that the lombok jar is available to gradle for
using the delombok ant task.
Then we configure the source files to
use.
Next we setup gradle to use the ant task.
Finally the copy task replaces the entire source tree with the delomboked version of the code. Obviously this could be removed to suit your needs.
I think the easiest way to delombok sources with gradle is:
task delombok {
description 'Delomboks the source code'
ant.taskdef(classname: 'lombok.delombok.ant.Tasks$Delombok', classpath: configurations.compile.asPath, name: 'delombok')
ant.mkdir(dir: 'build/src-delomboked')
ant.delombok(verbose: 'true', encoding: 'UTF-8', to: 'build/src-delomboked', from: 'src/main/java')
}
Using an Ant task is fine. No "Ant preconfiguration" should be necessary. Alternatively, you could use a JavaExec task to call delombok as in your last snippet. (JavaExec doesn't currently support the -jar option, so you'd have to name the main class.) Using a Maven plugin from Gradle isn't possible (except for executing Maven with an Exec task).
https://github.com/franzbecker/gradle-lombok
buildscript {
repositories {
maven { url 'https://plugins.gradle.org/m2/' }
}
dependencies {
classpath 'io.franzbecker:gradle-lombok:1.6'
}
}
apply plugin: 'java'
apply plugin: 'io.franzbecker.gradle-lombok'
UPD: at the moment I quite enough IntelliJ IDEA 2016.3 + Lombok plugin
and the contents build.gradle:
dependencies {
compileOnly 'org.projectlombok:lombok:+'
}

How to download dependencies in gradle

I have a custom compile task.
task compileSpeedTest(type: JavaCompile) {
classpath = files('build')
source = fileTree('src/test/java/speed')
destinationDir = file('bin')
}
Gradle doesn't try to download dependencies before its execution.
I cannot find anywhere a task name which does it to add it on list dependsOn.
Downloading java dependencies is possible, if you actually really need to download them into a folder.
Example:
apply plugin: 'java'
dependencies {
runtime group: 'com.netflix.exhibitor', name: 'exhibitor-standalone', version: '1.5.2'
runtime group: 'org.apache.zookeeper', name: 'zookeeper', version: '3.4.6'
}
repositories { mavenCentral() }
task getDeps(type: Copy) {
from sourceSets.main.runtimeClasspath
into 'runtime/'
}
Download the dependencies (and their dependencies) into the folder runtime when you execute gradle getDeps.
For Intellij go to View > Tool Windows > Gradle > Refresh All Projects (the blue circular arrows at the top of the Gradle window.
A slightly lighter task that doesn't unnecessarily copy files to a dir:
task downloadDependencies(type: Exec) {
configurations.testRuntime.files
commandLine 'echo', 'Downloaded all dependencies'
}
Updated for kotlin & gradle 6.2.0, with buildscript dependency resolution added:
fun Configuration.isDeprecated() = this is DeprecatableConfiguration && resolutionAlternatives != null
fun ConfigurationContainer.resolveAll() = this
.filter { it.isCanBeResolved && !it.isDeprecated() }
.forEach { it.resolve() }
tasks.register("downloadDependencies") {
doLast {
configurations.resolveAll()
buildscript.configurations.resolveAll()
}
}
I have found this answer https://stackoverflow.com/a/47107135/3067148 also very helpful:
gradle dependencies will list the dependencies and download them as a
side-effect.
This version builds on Robert Elliot's, but I'm not 100% sure of its efficacy.
// There are a few dependencies added by one of the Scala plugins that this cannot reach.
task downloadDependencies {
description "Pre-downloads *most* dependencies"
doLast {
configurations.getAsMap().each { name, config ->
println "Retrieving dependencies for $name"
try {
config.files
} catch (e) {
project.logger.info e.message // some cannot be resolved, silentlyish skip them
}
}
}
}
I tried putting it into configuration instead of action (by removing doLast) and it broke zinc. I worked around it, but the end result was the same with or without. So, I left it as an explicit state. It seems to work enough to reduce the dependencies that have to be downloaded later, but not eliminate them in my case. I think one of the Scala plugins adds dependencies later.
You should try this one :
task getDeps(type: Copy) {
from configurations.runtime
into 'runtime/'
}
I was was looking for it some time ago when working on a project in which we had to download all dependencies into current working directory at some point in our provisioning script. I guess you're trying to achieve something similar.
Building on top of Robert Elliot's answer. For whatever reason, if one is interested in downloading the dependencies to Gradle cache then copying to a local repository like maven's (by default ~/.m2/repository):
task downloadDependencies(type: Exec) {
configurations.implementation.files + configurations.runtimeOnly.files
finalizedBy "cacheToMavenLocal"
commandLine "echo", "Downloaded all dependencies and copied to mavenLocal"
}
task cacheToMavenLocal(type: Copy) {
from new File(gradle.gradleUserHomeDir, "caches/modules-2/files-2.1")
into repositories.mavenLocal().url
eachFile {
List<String> parts = it.path.split("/")
it.path = [parts[0].replace(".","/"), parts[1], parts[2], parts[4]].join("/")
}
includeEmptyDirs false
}
The task cacheToMavenLocal was copied and adapted from #Adrodoc55's answer on Gradle forum.
It is hard to figure out exactly what you are trying to do from the question. I'll take a guess and say that you want to add an extra compile task in addition to those provided out of the box by the java plugin.
The easiest way to do this is probably to specify a new sourceSet called 'speedTest'. This will generate a configuration called 'speedTest' which you can use to specify your dependencies within a dependencies block. It will also generate a task called compileSpeedTestJava for you.
For an example, take a look at defining new source sets in the Java plugin documentation
In general it seems that you have some incorrect assumptions about how dependency management works with Gradle. I would echo the advice of the others to read the 'Dependency Management' chapters of the user guide again :)
There is no task to download dependencies; they are downloaded on demand. To learn how to manage dependencies with Gradle, see "Chapter 8. Dependency Management Basics" in the Gradle User Guide.

Resources