How Do We Run a Gradle Dependency Report for Plugins? - gradle

Running gradle dependencies lists compile-time dependencies. IOW, it reports direct and transitive dependencies coming from the dependencies closure for the subproject.
What is the equivalent means of determining the transitive dependencies being used by Gradle plugins, the ones specified by the dependencies closure in the buildscript closure?
For example, suppose I have this top-level build.gradle file in an Android project:
buildscript {
repositories {
jcenter()
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.1'
classpath 'com.apollographql.apollo:gradle-plugin:0.3.1-SNAPSHOT'
}
}
allprojects {
repositories {
jcenter()
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
}
}
How do I find out what transitive dependencies are being pulled in by the com.apollographql.apollo:gradle-plugin:0.3.1-SNAPSHOT dependency?

Gradle provides various help tasks. A list of them is available via gradle tasks -all.
To access the buildscript dependencies, one can use the gradle buildEnvironment command, as described in the Gradle docs:
4.7.5. Listing project buildscript dependencies
Running gradle buildEnvironment visualises the buildscript dependencies of the selected project, similarly to how gradle dependencies visualises the dependencies of the software being built.
As addition, CommonsWare stated, that the command must be executed from the project directory.

Related

build.gradle buildscript dependencies vs. dependencies?

Can someone explain to me how depedencies listed in the "buildscript" in the build.gradle file are different than regular dependencies listed in the dependencies block { } ? and why they have to be listed with the syntax "implementation"? I've googled this and responses say the dependencies in the buildscript and used to "build the project" but I don't understand this? can anyone give a more clear picture and answer?
buildscript:
buildscript
{
repositories
{
maven {
url 'myMavenFeed'
credentials {
username "myUsername"
password myPassword
}
}
mavenCentral()
jcenter()
}
dependencies
{
classpath "com.microsoft.azure.sdk.iot:iot-device-client:1.14.1"
}
}
Dependencies block:
dependencies
{
compile group: 'com.microsoft.azure.sdk.iot', name: 'iot-device-client', version: '1.16.0'
}
Can someone explain to me how depedencies listed in the "buildscript" in the build.gradle file are different than regular dependencies listed in the dependencies block { } ?
Dependencies defined in the buildscript { } block are dependencies to use to build your project. These dependencies are available to use in your Gradle build file (build.gradle or build.gradle.kts)
Dependencies defined in the dependencies { } are for your application code.
So for your samples in your questions, does it make sense for Gradle (the build system) to have iot-device-client on its classpath? Why does a build system need iot-device-client on its classpath to build your project? It doesn't make sense therefore it should be removed.
Now let's say you are developing an application the requires some functionality or class from iot-device-client. You need a way to add this library to your application's code/classpath. You when then declare it as a dependency as you have done above:
dependencies {
implementation("com.microsoft.azure.sdk.iot:iot-device-client:1.16.0")
}
References:
External dependencies for the build script
Declaring depenedncies
and why they have to be listed with the syntax "implementation"?
implementation is known as a configuration: A Configuration represents a group of artifacts and their dependencies
There are many more configurations depending on the plugins you apply to your project. For example, if you apply the Java plugin:
plugins {
id("java")
}
The following configurations are available to use:
implementation
compileOnly
compileClasspath
...and many more
Each one has their own meaning/usage and I strongly suggest reading about them here.

how to declare dependency version in one place for many gradle projects

I work on a project with multiple grails services, plugins and libraries, all built with gradle with their dependencies declared in build.gradle files, one per project, this makes sense, I hope.
In maven I used to be able to declare versions of all dependencies in one parent project pom, or a pom template, and only include the dependencies in the projects that required them without the versions. This made upgrading dependencies easy in one place. Is there a simple way to do this in gradle?
Pseudocode example:
master_template/build.gradle
dependencies {
joda-time:joda-time:2.9.1
cglib:cglib:3.2.9
javax.servlet:javax.servlet-api:3.1.0
}
service_a/build.gradle
parent: master_template
dependencies {
joda-time:joda-time
javax.servlet:javax.servlet-api
}
service_b/build.gradle
parent: master_template
dependencies {
cglib:cglib
javax.servlet:javax.servlet-api
}
You can create a multi module project like you would do in maven with a parent pom.
In order to manage the dependency in the parent, I use the spring dependency management plugin.
You parent build.gradle would look like:
subprojects {
apply plugin: "io.spring.dependency-management"
sourceCompatibility = 1.8
targetCompatibility = 1.8
check.dependsOn dependencyCheckAggregate
repositories {
mavenLocal()
jcenter()
// other repos
}
dependencyManagement {
def jacksonVersion = "2.+"
dependencies {
dependency "com.fasterxml.jackson.core:jackson-annotations:$jacksonVersion"
dependency "com.fasterxml.jackson.core:jackson-core:$jacksonVersion"
dependency "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion"
dependency "com.fasterxml.jackson.datatype:jackson-datatype-jdk8:$jacksonVersion"
dependency "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jacksonVersion"
}
}
}
Now, you can add dependencies to your submodules without specifying version.
You can easily achieve what you want by using Gradle's default apply from: 'other.gradle', so no additional plugins are needed.
In my micro-service project I'm using something like that:
common-gradle/env.gradle
apply plugin:'groovy'
ext.compile = [ 'joda-time:joda-time:2.9.1', 'cglib:cglib:3.2.9` ]
ext.testCompile = [ 'org.spockframework:spock-core:1.3-groovy-2.5' ]
common-gradle/dependencies.gradle
dependencies {
compile ext.compile
testCompile ext.testCompile
}
And the usage
service_a/build.gradle
apply from:'../common-gradle/env.gradle'
ext.compile << 'ch.qos.logback:logback-classic:1.2.3'
apply from:'../common-gradle/dependencies.gradle'
Thus each of my build.gradle files contain only 3-5 lines of critical information like project name and version.
You don't need to import the common-gradle as a project in your IDE, you can simply use symlinks to avoid using external references. Also during build on a Jenkins-like pipeline, the only thing you have to do is to check out the common-gradle repo into your working dir.

Gradle with a local pom dependency picks up wrong version

My build.gradle references a local maven pom. I have enabled the mavenLocal() repository and have added the jar as a compile time dependency (eg. my-local-lib, as shown below).
repositories {
mavenCentral()
mavenLocal()
}
dependencies {
compile (group: 'com.company', name: 'my-local-lib', version: '1.0-SNAPSHOT')
}
Gradle indeed picks it up and adds it as a dependency. My-local-lib, however, is itself dependent on another library as specified in its pom.xml, but gradle fails to pick up the correct version specified in the pom.xml, and instead chooses a much earlier version. This particular jar dependency is not a dependency on any other library.
Is this a known issue? Could it be due to my-local-lib being a SNAPSHOT version? Is there a way that I can enforce gradle to respect the versions specified in the libraries?
Try to add the following piece of code:
configurations.all {
resolutionStrategy {
cacheChangingModulesFor 0, 'seconds'
}
}
to build.gradle script.

Gradle NoClassDefFoundError in jar dependency

I have developed a custom Gradle plugin and assembled as jar. This plugin has one dependency:
plugin/build.gradle
dependencies {
compile 'com.jcraft:jsch:0.1.53'
}
I have included my plugin in another consumer project (as jar in libs):
consumer/build.gradle
apply plugin: 'gg-release-plugin'
buildscript {
repositories {
flatDir {
dirs 'libs'
}
mavenCentral()
}
dependencies {
classpath 'com.myplugin.plugin:myplugin:1.0'
}
}
Everything works fine, but when code that uses classes of the dependency com.jcraft:jsch:0.1.53 is executed, I get an error:
java.lang.NoClassDefFoundError: com/jcraft/jsch/JSch
What am I doing wrong? How can I include the dependencies in jar file?
Seems, you've created a plugin jar library with compile time depnedency, that is not included anywhere in your final jar.
You can try to create your plugin jar as a fat jar, using Gradle FatJar plugin or something else. In that case, you'll have a single jar with all the dependent classes inside. But this could lead to problems, if someone will use the same library.
Or you can try to provide a JSch library together with your plugin jar and make a consumer build script dependency like:
buildscript {
repositories {
flatDir {
dirs 'libs'
}
mavenCentral()
}
dependencies {
classpath 'com.myplugin.plugin:myplugin:1.0'
classpath 'com.jcraft:jsch:0.1.53'
}
}
As I know, if you use a Maven repo to publish your plugin, you can provide a pom.xml to describe all the plugin's dependencies, but as I see, you are using a flatDir for it, so, it seems not to be possible.

Gradle custom plugin dependencies

If a have a custom plugin which handles the building and deploying of a specific component, where do I list the dependencies (other components in my system) which are required for the build?
Dependencies for your Gradle plugins should be listed in the buildscript portion of the build.gradle file. See this chapter of the User Guide, which also has an example:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:0.4.1"
}
}
apply plugin: "com.jfrog.bintray"
If your custom plugin depends on jar files on your local machine, I gather that you need to add those files as a "flatDir" repository in the repositories entry, as described here:
repositories {
flatDir {
dirs 'lib1', 'lib2'
}
}

Resources