Gradle: How do you include your own library as part of build? - gradle

I have a commons gradle project which is a shared library for all my other projects.
In the build.gradle of dependent project, I included the commons jar as following:
dependencies {
...
runtime files('../commons/build/libs/commons-1.0.jar')
}
And this builds fine with the relative path. But this feels like hard-coding a specific library. What is the standard way to achieve the builds in this case?

You can publish the common jar to Your local maven repository. But If You are developing with in a team, You should publish to a repository manager where other parties have also access to.
And in the dependent projects You simply add this common jar, like You are adding a third party library. With this way You don't have to store dependent jar files on Your version control system. When projects are developed by different parties, this way would be more convenient.
Example of using mavenlocal
// Common project build.gradle
apply plugin: 'maven-publish'
version = '2.0'
...
publishing {
publications {
maven(MavenPublication) {
groupId = 'com.gradle.sample'
artifactId = 'project1-sample'
from components.java
}
}
}
You can use gradle publishToMavenLocal to publish common project to mavenlocal. (Dependent projects can not use the new versions of common jar, unless You publish it to mavenlocal in this case)
// Dependent project build.gradle
repositories {
mavenLocal()
}
dependencies {
implementation 'com.gradle.sample:project1-sample:2.0'
....
}
Check the following link for details.
https://docs.gradle.org/current/userguide/publishing_maven.html

Related

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.

How to structure Gradle builds to allow building interdependent libraries

I built a small little test project to see if Gradle would solve this problem we currently have with Maven. We have 200 little libraries, all of them Maven projects, whenever you do a clean checkout, you have to mvn install each of them individually
To simulate such a scenario, i've created 4 modules:
root
- jvaas-gson
- jvaas-jackson
- jvaas-json
- jvaas-provider
Both jvaas-gson and jvaas-jackson depends on jvaas-json and jvaas-provider. jvaas-json only depends on jvaas-provider.
If some external application wants to include JSON capabilities, they should only have to include jvaas-gson or jvaas-jackson which uses an interface in jvaas-json (as i said, this is just experimenting with it, actual use-case would be to switch out email providers, payment providers etc only having to change a line in the Gradle build script)
In jvaas-provider i have a settings.gradle.kts
rootProject.name = "jvaas-provider"
and a build.gradle.kts
import org.jetbrains.kotlin.gradle.plugin.getKotlinPluginVersion
group = "io.jvaas"
version = "1.3.0"
plugins {
`maven-publish`
kotlin("jvm") version("1.3.10")
id("org.jetbrains.dokka") version "0.9.16"
}
repositories {
jcenter()
}
dependencies {
implementation(kotlin("stdlib", getKotlinPluginVersion()))
testImplementation("org.junit.jupiter:junit-jupiter-api:5.3.1")
}
publishing {
repositories {
mavenLocal()
}
}
In jvaas-json i'm trying to access one of the classes in jvaas-provider, so i've added it to the settings.gradle.kts
rootProject.name = "jvaas-json"
include("jvaas-provider")
and the build.gradle.kts
import org.jetbrains.kotlin.gradle.plugin.getKotlinPluginVersion
group = "io.jvaas"
version = "1.3.0"
plugins {
`maven-publish`
kotlin("jvm") version("1.3.10")
id("org.jetbrains.dokka") version "0.9.16"
}
repositories {
jcenter()
}
dependencies {
implementation(kotlin("stdlib", getKotlinPluginVersion()))
implementation(group = "io.jvaas", name = "jvaas-provider", version = "$version")
testImplementation("org.junit.jupiter:junit-jupiter-api:5.3.1")
}
Inside jvaas-json, i'm trying access one of the classes i created inside jvaas-provider, but it's not resolving.
Without having to manually install jvaas-provider in the local maven repo (mvn install), is it possible to use it as a dependency inside jvaas-json? If so, what should i be changing in my Gradle build scripts and Settings files?
Paul on the Kotlin Slack just answered my question just before i could hit Post on my StackOverflow question, so posting this as QA-style, maybe it'll help somebody else in the future.
Gradle has something called composite builds which allows you to include other projects / libraries inside your project without having to install them to a local maven repo first.
For the above example to work with composite builds, all i had to do was change something in the settings.gradle.kts file:
rootProject.name = "jvaas-json"
includeBuild("../jvaas-provider")

Gradle : Something like Maven Parent POM

In our company, many of the different projects use similar technology stack and will have many common features.
So, we want to maintain the common features, dependencies etc. in one common file and refer it in the other projects.
In maven, it is something like creating a separate maven project with the common dependency information and refer that in the other projects as .
I want to do something similar to the maven parent project in gradle, which can be used by all different projects.
I googled for that, but could not find a concise information on how to do that.
We are not allowed to use external thirdparty plugins.
It would be great if someone could explain it how to do that.
in gradle you can do that, but for it you need to have external plugin, otherwise it is not possible at least for now. I have achieved it in this way:
buildscript {
repositories { jcenter() }
dependencies {
classpath 'com.netflix.nebula:nebula-dependency-recommender:4.3.0'
}
}
allprojects {
apply plugin: 'nebula.dependency-recommender'
apply plugin: 'groovy'
apply plugin: 'java'
sourceCompatibility = 1.8
targetCompatibility = 1.8
repositories {
mavenCentral()
jcenter()
maven { url "http://repo1.maven.org/maven2/" }
maven { url "REPOSITORY_OF_YOUR_PARENT_POM.XML" }
}
dependencyRecommendations {
mavenBom module: 'YOUR_PARENT_POM_GROUP:YOUR_PARENT_POM_ID:YOUR_PARENT_POM_VERSION'
}
}
where:
REPOSITORY_OF_YOUR_PARENT_POM.XML - any system like nexus or something else accessible for maven
YOUR_PARENT_POM_GROUP - your parent pom project group (e.g. com.foo.bar.parent)
YOUR_PARENT_POM_ID - your parent pom id (e.g. projects-parent)
YOUR_PARENT_POM_VERSION - your parent pom project version (e.g. 1.0.1)
so, if the external dependency to netflix.nebula is fine , than you can go in this way
Gradle has many extension mechanisms for leveraging build logic located outside of the main script.
A simple thing that can be done is to use an external build script, which can be sourced from the local file system or through an URL, see the documentation on this topic.
If that solution gets too problematic, then you can move to packaging a real plugin that others can apply and potentially configure.
This will allow you to configure much more than dependencies for example.

Publish reusable gradle tasks

I would like to publish some common parts of build.gradle file to be reusable in different projects (using apply from: url_to_file construction). To achieve this I've created a project called gradle-common that contains those common build files, with this build.gradle file:
group 'org.example'
version '0.1.0'
apply plugin: 'maven-publish'
publishing {
publications {
mavenJava(MavenPublication) {
artifact source: file('files/first.gradle'), classifier: 'first'
}
mavenJava(MavenPublication) {
artifact source: file('files/second.gradle'), classifier: 'second'
}
}
repositories {
mavenLocal()
}
}
Files after publishing in maven repository there are files like:
gradle-common-0.1.0-first.gradle
gradle-common-0.1.0-second.gradle
And my question is: how can I remove version number from published artifacts and the classfier? For me ideal files would be:
first.gradle
second.gradle
There are many different answers to your question, but I think you are trying to create something that a plugin usually does without creating a plugin.
The best way to add functionality to multiple gradle projects is to create a plugin. You can also leverage Rules which this simple tutorial doesn't show, but you can inspect some of the gradle native plugins, such as maven-publish.
To answer your question, it is not possible to publish an artifact to a maven repository without a version. You have to download it with a version (you can use my-artifact:1+ to download the latest) and then strip the version yourself.
I am also wondering how are you planning to include these files to your specific gradle files. You won't be able to use them as dependencies, since the dependency resolution happens after the scripts are read. If you are downloading them somehow before the script runs, then you probably don't need a maven repository for that.

How do I define a simple Gradle project with only a single jar file?

I have a Gradle project that depends on an external jar file. Currently I'm defining the dependency like this:
dependencies {
compile files('/path/to/my/jar/library.jar')
}
However I want to include it as a project dependency instead, like this:
dependencies {
compile project(':whatGoesHere?')
}
I assume I need to define a new Gradle project that contains the jar file but I don't know how to do this. I'm wondering about things like:
Do I just need to create a new build.gradle or are there more steps?
What would go in the build.gradle file?
Assume the new project contains nothing but the jar file (since it does). Also assume I know almost nothing about Gradle (because I don't!).
P.S. If it matters, this is an Android Gradle project.
As a roundup for our discussion, I'll bring simple example of "build.gradle" file, using maven local and maven central repositories:
apply plugin: 'maven'
apply plugin: 'java'
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
compile 'commons-io:commons-io:2.4'
testCompile 'junit:junit:4.11'
}
Explanation:
"apply plugin: 'maven'" enables maven plugin, which is needed for dependency download.
"apply plugin: 'java'" enables java compilation tasks for your project.
"repositories" declares one or more repositories (maven or ivy), from where artifacts (jar libraries) will be downloaded.
"mavenLocal" refers to so-called local maven repository, which is located in "~/.m2/repository" folder on your computer. local maven repository effectively caches external repositories, but it also allows installation of local-only artifacts.
"mavenCentral" refers to maven central.
"dependencies" lists your project dependencies, either other projects or artifacts (jars).
"compile" is a configuration supported by "java" and "groovy" plugins, it tells gradle: "add these libraries to the classpath of the application during compilation phase".
"testCompile" is another configuration supported by "java" and "groovy" plugins, it tells gradle: "add these libraries to the classpath of the application during test phase".
'commons-io:commons-io:2.4' is "coordinates" of the artifact within maven repository, in form group:name:version.
You can search for well-known java libraries at address: http://mvnrepository.com/ and then include their coordinates in "build.gradle". You don't need to download anything - gradle does it for you automatically.

Resources