gradle.rst
author Oleksandr Gavenko <gavenkoa@gmail.com>
Sun, 15 Nov 2020 16:55:51 +0200
changeset 2458 28c248a41a85
parent 2413 ceca880171c3
child 2467 0498f0cc9966
permissions -rw-r--r--
Altering user home.


========
 Gradle
========
.. contents::
   :local:

Getting help
============
::

  $ gradle --help

Stopping server
===============
::

  $ gradle --stop

Altering user home
==================

``GRADLE_USER_HOME`` controls user home.

https://docs.gradle.org/current/userguide/build_environment.html
  Build Environment. Gradle properties. ``GRADLE_USER_HOME`` directory.

Logging
=======

Gradle uses modified Slf4j: ``org.gradle.api.logging.Logger``.

Logging level can be set with ``org.gradle.api.logging.LogLevel``::

  logger.log(LogLevel.LIFECYCLE, "Unzipping {}...", zipFile);

``Project`` and ``Task`` has ``logger`` object with levels::

  logger.error "..."
  logger.quiet "..."
  logger.warning "..."
  logger.lifecycle "..."
  logger.info "..."
  logger.debug "..."

``println`` is printed on ``quiet`` level.

Make Gradle quiet::

  $ gradle -q ...
  $ gradle --quiet ...

Show only errors/warnings::

  $ gradle -w ...
  $ gradle --warn ...

Make Gradle verbose::

  $ gradle -i ...
  $ gradle --info ...

Make Gradle to print debug output::

  $ gradle -d ...
  $ gradle --debug ...

Debugging Gradle
================

Enable debugging and disable server mode::

  gradle -Dorg.gradle.debug=true --no-daemon ...

Then attach by Java debugger to port 5005.

Alternatively::

  GRADLE_OPTS='-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005' gradle  --no-daemon ...

To investigate interface & values of object::

  println it.metaClass.metaMethods*.name.sort().unique()
  println it.metaClass.methods*.name.sort().unique()
  println it.properties.entrySet()*.toString().sort().toString().replaceAll(", ","\n")

https://docs.gradle.org/current/userguide/troubleshooting.html
  Attaching a debugger to your build.
https://stackoverflow.com/questions/22203947/how-to-dump-all-gradle-values-used-for-build
  How to dump all gradle values used for build.

Managing tasks
==============

List tasks::

  $ gradle tasks

Getting list of supported tasks in each subproject::

  $ gradle tasks --all

Check execution path or debug task dependencies::

  $ gradle -m compile
  $ gradle --dry-run compile

Getting help on task::

  $ gradle help --task build
  $ gradle -q help --task build

Similar but to each task::

  $ gradle model

Skip task during build with ``-x`` option::

  $ gradle -x test build
  $ gradle -x :core:build :client:build

Skipt task programmatically::

  gradle.startParameter.excludedTaskNames.add "jar"

Working with subprojects
========================

Getting list of subprojects::

  $ gradle projects

Running build on specific subproject::

  $ gradle :$SUB:clean
  $ gradle -p $SUB clean

If subproject lies in hierarchy::

  $ gradle :$SUB/$SUBSUB:clean
  $ gradle -p $SUB/$SUBSUB clean

Skip building dependent modules, build just current module::

  $ gradle -a build
  $ gradle --no-rebuild build
  $ gradle -a :client:build

Creating multilevel project::

  $ mkdir $PRJROOT
  $ cd $PRJROOT
  $ mkdir lvl1 lvl1/lvl2
  $ touch build.gradle lvl1/build.gradle lvl1/lvl2/build.gradle
  $ { echo include "'lvl1'"; echo include "'lvl1/lvl2'"; } >settings.gradle
  $ gradle projects

``settings.gradle`` can include per line or a list of subprojects::

  include 'sub1', 'sub2', 'sub2'
  include 'lvl1'
  include 'lvl1/lvl2'

https://docs.gradle.org/current/userguide/intro_multi_project_builds.html
http://stackoverflow.com/questions/16976214/gradle-build-only-one-module

Debugging build
===============

Enable better logging::

  $ gradle -i ...
  $ gradle --info ...
  $ gradle -d ...
  $ gradle --debug ...

Enable stacktraces::

  $ gradle --stacktrace

Review deprecation::

  $ gradle --warning-mode=all --stacktrace

Profiling build
===============
::

   $ gradle --profile

To use build scans accept EULA::

  buildScan {
    termsOfServiceUrl = 'https://gradle.com/terms-of-service'
    termsOfServiceAgree = 'yes'
  }

then run::

  $ gradle --scan

Running completely isolated build
=================================

To avoid using global cache and for really clean build use::

  $ gradle --no-daemon -g _tmp
  $ gradle --no-daemon --gradle-user-home ./.gradle.local

Build sources
=============
::

  $ gradle compileJava
  $ gradle compileTestJava

Build with additional options and checks::

  compileJava {
    options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
  }
  compileTestJava {
    options.encoding = 'UTF-8'
    options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
  }

To apply change recursively to subprojects::

  subprojects {
      tasks.withType(JavaCompile) {
          options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
      }
  }

Run main class
==============
::

  $ gradle run

Run tests
=========

To run test::

  $ gradle test

To select specific test or pattern use ``--tests`` option, like::

  $ gradle test --tests com.evil.UtitTest
  $ gradle test --tests com.evil.UtitTest.login
  $ gradle test --tests '*'BasicTest.login
  $ gradle test --tests '*BasicTest.calc*'

To skip tests in build::

  $ gradle -x test build

To continue testing after fixing test::

  $ gradle test --continue

Alternative solution involves passing system property with ``build.gradle``::

  test.onlyIf { ! Boolean.getBoolean('skip.tests') }

To run tests with additional registered checks::

  $ gradle check

.. note::
   ``--rerun-tasks`` option *specifies that any task optimization is ignored*.
   If you are not using build cache it reruns tests and all dependent tasks::

     $ gradle test --rerun-tasks

  See https://stackoverflow.com/questions/29427020/how-to-run-gradle-test-when-all-tests-are-up-to-date

By default ``System.out`` and ``Sysyem.err`` redirected so you wouldn't see
anything about test on console.

Quick way to see test output is::

  $ gradle test -i

Alternatively configure ``test`` task::

  test {
    testLogging {
      events "passed", "skipped", "failed" //, "standardOut", "standardError"

      showExceptions true
      exceptionFormat "full"
      showCauses true
      showStackTraces true

      showStandardStreams = false
    }
  }

List project dependencies
=========================

List of project execution dependencies (it also download dependencies)::

  $ gradle dependencies
  $ gradle dependencies --configuration compile
  $ gradle dependencies -p $SUBPROJ
  $ gradle :$SUBPROJ:dependencies
  $ gradle :$SUBPROJ:dependencies --configuration testCompile

List of project plugin dependencies::

  $ gradle buildEnvironment
  $ gradle buildEnvironment -p $SUBPROJ
  $ gradle :$SUBPROJ:buildEnvironment

Paths to dependencies can be printed via task::

  task printDepPaths {
    doLast { configurations.runtime.each { println it } }
  }

All dependencies can be copied to single directory via task::

  task copyRuntimeLibs(type: Copy) {
    into "lib"
    from configurations.runtime
    // from configurations.testRuntime - configurations.runtime
  }

List of configurations::

  configurations.each { println it.name }

For each configuration ``build<ConfigurationName>`` and ``upload<ConfigurationName>`` are defined.

Configuring external dependencies
=================================

Adding large well known artifact repositories::

  repositories {
    mavenCentral()
    jcenter()
  }

``mavelLocal()`` for local ``~/.m2`` or whenever Maven ``settings.xml`` is pointing.

Adding custom repositories::

  repositories {
    maven { url "http://repo.example.com/maven2" }
    ivy { url "http://repo.example.com/ivy" }
    maven {
      url "http://repo.example.com/maven2"
      username "ro-user"
      password "pas$$word"
    }
  }

Excluding transitive dependencies::

  compile 'org.springframework:spring-web:4.3.10.RELEASE' {
      exclude group: 'com.google.code.gson', module: 'gson'
  }

  implementation project(':core'), {
      exclude group: 'org.quartz-scheduler'
  }

  configurations.all {
      exclude group: 'com.google.code.gson', module: 'gson'
  }

  configurations.runtime {
      exclude group: 'com.google.code.gson', module: 'gson'
  }

  configurations {
      implementation {
          exclude group: 'javax.jms', module: 'jms'
      }
  }

Forcing a specific version of a transitive dependency::

  configurations.all {
      resolutionStrategy.force 'com.google.code.gson:gson:2.8.1'
  }

Declaring dependency on module in multi-module build::

  compile project(':core')

List project properties
=======================
::

  $ gradle properties
  $ gradle :$SUBPROJ:properties
  $ gradle properties -p $SUBPROJ

Well known properties
=====================

``rootDir``, ``projectDir``, ``buildDir`` are of ``java.io.File`` type.

``tasks`` refers to task set.

``project``, ``subprojects``, ``rootProject`` refer to various Project instances.

Bootstrap project structure
===========================

This creates simple project with Gradle boilerplate files::

  $ gradle init --type java-library

To convert Maven project (with ``pom.xml`` file) to Gradle project use::

  $ gradle init --type pom

https://docs.gradle.org/current/userguide/build_init_plugin.html
  Official docs on ``init`` plugin.

Gradle wrapper
==============

With Gradle v2.4 and above::

  $ cd $PROJ
  $ gradle wrapper --gradle-version 3.5

It will add ``gradle/wrapper/gradle-wrapper.jar`` to project root and next call
to ``./gradlew`` download Gradle distribution from ``distributionUrl`` parameter
from ``gradle/wrapper/gradle-wrapper.properties`` file. Dictribution will be
cached in ``~/.gradle/wrapper/dists.gradle/wrapper/dists`` directory so next
calls won't require download.

Alternatively define task::

  task wrapper(type: Wrapper) {
      gradleVersion = '2.0'
  }

Update Gradle wrapper version with::

  $ gradle --version
  Gradle 4.0.1
  $ gradle wrapper --gradle-version 4.9

To increase security add ``distributionSha256Sum`` parameter to ``gradle-wrapper.properties`` file.
Distribution SHA-256 sum can be obtained via ``shasum`` utility.

https://docs.gradle.org/current/userguide/gradle_wrapper.html
  Official docs.

Managing Gradle cache
=====================

Work in offline mode with ``--offline`` option.

Invalidate cache (force re-downloading dependencies) with
``--refresh-dependencies`` option.

Alternatively remove ``~/.m2/repository/`` and ``~/.gradle/caches`` directories.

Gradle cached modules declared as *changing*::

  dependencies {
    compile("com.evil:evil-api:1.0.1-SNAPSHOT") { changing=true }
  }

Default timeout is 24 hours and can be reset/changed via::

  configurations.all {
      resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
  }

Download sources and javadoc of dependencies
============================================

To download sources and javadoc of dependencies to local ``~/.gradle`` cache add
``idea`` plugin to your ``build.gradle``::

  apply plugin: 'idea'
  idea.module.downloadJavadoc = true
  idea.module.downloadSources = true

and invoke plugin::

  $ gradle idea

To wipe out Idea projects file after plug-in run::

  $ gradle cleanIdea

Dependencies between tasks
==========================

Direct dependency::

  task A {
    dependsOn B, C
  }
  A.dependsOn D, E

Cleanup actions::

  task A {
    dependsOn startServer
    finalizedBy stopServer
  }

To enforce order without enforcing dependency::

  task A {
    mustRunAfter B
  }

Declare dependencies programmatically::

  dependsOn project.tasks.matching { it.name.endsWith "Test" }

Apply task on condition::

  task upload {
      onlyIf { System.getProperty("debug") != null }
      doLast { println "In debug mode." }
  }

Accessing task graph
====================

Process task graph when it is already populated::

  gradle.taskGraph.whenReady { graph ->
    if (graph.hasTask(":release")) { ... }
  }

``gradle.taskGraph`` is safe to access inside ``doFirst`` / ``doLast``::

  task someTask {
    doLast {
      if (gradle.taskGraph.hasTask(":someTask")) {  }
    }
  }

List all tasks that will be executed in current build::

  println gradle.taskGraph.allTasks

Applying pluings
================
::

   apply from: "plugins/my.gradle"

Publishing artifacts
====================

https://docs.gradle.org/current/userguide/publishing_setup.html
  Publishing a project as module.
https://docs.gradle.org/current/userguide/publishing_customization.html
  Customizing publishing.
https://www.jfrog.com/confluence/display/JFROG/Gradle+Artifactory+Plugin
  Gradle Artifactory Plugin.
https://github.com/jfrog/build-info
  Project that holds Artifactory integration for Gradle (``build-info-extractor-gradle``).