How to import dependecies from build.gradle to pom.xml - maven

I use maven-publish plugin for deploying android library(.aar).
My library has another dependencies, which are also .aar
How can I import all dependencies from build.gradle, dependencies section:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.android.support:design:23.1.1'
compile 'com.android.support:support-v4:23.1.1'
compile ('com.android.support:recyclerview-v7:22.2.1'){
exclude group: 'com.android.support', module: 'support-v4'
}
compile 'com.inthecheesefactory.thecheeselibrary:stated-fragment-support-v4:0.10.0'
//Http communication, websockets, etc.
compile 'com.squareup.okhttp:okhttp:2.4.0'
compile 'com.squareup.retrofit:retrofit:1.9.0'
//Fonts
compile 'uk.co.chrisjenx:calligraphy:2.1.0'
//Unit tests
testCompile 'junit:junit:4.12'
testCompile 'org.mockito:mockito-core:1.9.5'
//Other
compile ('org.apache.commons:commons-lang3:3.4'){
exclude group: 'org.apache.httpcomponents'
}
//Reactive programmnig
compile 'io.reactivex:rxjava:1.0.13'
compile 'io.reactivex:rxandroid:0.25.0'
compile 'com.github.bumptech.glide:glide:3.6.1'
}
To generated pom.xml dependencies section:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.my.sdk</groupId>
<artifactId>SDK</artifactId>
<version>0.0.1</version>
<packaging>aar</packaging>
<dependencies>
...
</dependencies>
</project>
I found some explanation how to do similar things:
Optional Gradle dependencies for Maven libraries
How to change artifactory runtime scope to compile scope?
https://issues.gradle.org/browse/GRADLE-1749
http://www.scriptscoop.net/t/6ac07fb41846/how-to-maven-publish-a-gradle-project-jar-with-provided-scope.html
So, I understood, that I should use pom.withXml, import all dependecies from project.configurations.compile.allDependencies with scope compile, and put it into asNode().dependencies
But I'm not familiar with it, and I think I doing something wrong. Here is my current code:
publishing {
publications {
maven(MavenPublication) {
artifact "${project.buildDir}/outputs/aar/${project.name}-release.aar"
artifactId = POM_ARTIFACT_ID
groupId = GROUP
version = VERSION_NAME
// Task androidSourcesJar is provided by gradle-mvn-push.gradle
//artifact androidSourcesJar {
// classifier "sources"
//}
pom.withXml {
def depsNode = asNode().dependencies.'*'
project.configurations.compile.allDependencies.each { dep ->
if(dep.name != null && dep.group != null && dep.version != null) {
def depNode = new Node(null, 'dependency')
def groupIdNode = new Node(depNode, 'groupId', dep.getGroup())
def artifactIdNode = new Node(depNode, 'artifactId', dep.getName())
def versionNode = new Node(depNode, 'version', dep.getVersion())
depsNode.add(depNode)
println depsNode
}
}
}
}
}
repositories {
maven {
credentials {
username System.getenv('NEXUS_USER_NAME')
password System.getenv('NEXUS_PASSWORD')
}
url "http://nexus-repo"
}
}
}

To publish a .aar library with the dependencies listed correctly in pom.xml, it might be easier to use this plugin, rather than assemble the dependencies section yourself using the maven-publish plugin.
To apply plugin:
plugins {
id "com.github.dcendents.android-maven" version "1.3"
}
and run task install to push library to local .m2 repo.
You can override the repo being published to like this:
install {
repositories {
mavenDeployer {
repository(...)
}
}
}
You can of course, continue to use the maven-publish plugin if you so prefer. In your code, you're looking for depsNode which does not already exist. You likely need to create a new Node for depsNode and add it to the pom first. Or just use append:
pom.withXml {
def depsNode = asNode().appendNode('dependencies')
configurations.compile.allDependencies.each { dep ->
def depNode = depsNode.appendNode('dependency')
depNode.appendNode('groupId', dep.group)
depNode.appendNode('artifactId', dep.name)
depNode.appendNode('version', dep.version)
//optional add scope
//optional add transitive exclusions
}
}
The caveat here is that, you still need to handle exclusions correctly. Also, if you have variants in your project, and have different compile configurations such as androidCompile or somethingElseCompile, you need to handle those correctly as well.

You can update the dependencies with the dependencies of another project or library in the maven publish task. This has to be done before jar generation task. In this way, the changes will be reflected in the pom generation and no need for pom xml manipulation. getDependencies is the method that you extract those dependencies and you should implement it ;)
This is the snippet in the publish task
artifactId = POM_ARTIFACT_ID
groupId = GROUP
version = VERSION_NAME
project.configurations.implementation.withDependencies { dependencies ->
dependencies.addAll(getDependencies(project))
}
from components.java

Related

Unable to resolve library using Gradle. Resolved using Grape

I'm fairly new to Groovy and I'm trying to wrap my head around Gradle. If I import the org.jvnet.hudson.plugins through Grapes it works perfectly and the dependency is resolved. But if I try to retrieve the dependency using Gradle the dependency is not resolved.
The package org.eclipse.hudson:hudson-core:3.2.1 works with both Gradle and Grape.
A dependency that is not resolved using Gradle
compile 'org.jvnet.hudson.plugins:checkstyle:3.42'
A dependency which is resolved using Grape
#Grab('org.jvnet.hudson.plugins:checkstyle:3.42')
A dependency which is resolved using Gradle
compile 'org.eclipse.hudson:hudson-core:3.2.1'
Error during Gradle build
line 3, column 1.
import hudson.plugins.checkstyle.CheckStyleResultAction;
^
The build.gradle
apply plugin: 'groovy'
repositories {
mavenCentral()
maven {
url "http://repo.jenkins-ci.org/releases/"
}
}
configurations {
ivy
}
sourceSets {
main {
groovy {
srcDirs = ['src/']
}
}
test {
groovy {
srcDirs = ['test/']
}
}
}
dependencies {
compile 'org.codehaus.groovy:groovy-all:2.4.11'
compile "org.apache.ivy:ivy:2.4.0"
ivy "org.apache.ivy:ivy:2.3.0"
// Works
compile 'org.eclipse.hudson:hudson-core:3.2.1'
// Does not work
compile 'org.jvnet.hudson.plugins:checkstyle:3.42'
}
tasks.withType(GroovyCompile) {
groovyClasspath += configurations.ivy
}
You're probably not actually downloading the jar you think you are. Looks like the default artifact that comes back from the org.jvnet.hudson.plugins:checkstyle:3.42 dependency is actually a file named checkstyle-3.42.hpi.
To get the jar which contains the classes instead, use:
compile group: 'org.jvnet.hudson.plugins', name: 'checkstyle', version:'3.42', ext: 'jar'
Then that class will be found on your classpath (and you'll be on to locating the next missing dependency).

Building a fully executable Spring Boot 1.3 war from a Gradle multi project build

I'm trying to build a fully executable WAR using Spring Boot 1.3 as per https://docs.spring.io/spring-boot/docs/current/reference/html/deployment-install.html. If I build a single Gradle project, it all works fine, but I havea multi project build, where I have a "root" project and then several projects underneath it, and I cannot get it to build anything but a standard, "fat" WAR file, without the providedRuntime of Jetty and without the scripts to make it run.
Does anyone know how to do this?
In my root project, I have the following (abridged):
buildscript {
repositories {
mavenCentral()
}
ext {
springBootVersion = '1.3.0.RELEASE'
}
dependencies {
classpath "org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion"
}
}
allprojects {
//Put instructions for all projects
repositories {
mavenCentral() // jcenter is missing spring-orm.4.1.6.RELEASE jar file so try mavenCentral first
jcenter {
url "http://jcenter.bintray.com/"
}
maven { url 'http://repo.opensourceagility.com/release' }
}
}
subprojects {
apply plugin: 'java'
apply plugin: 'spring-boot'
}
and then in the subproject which is a web project, and which I'm trying to build, I have:
apply plugin: 'war'
dependencies {
// Include related projects
compile project(':project-model')
compile project(':project-dynamoDB')
// Core Spring Boot - note version is set in main build.gradle file
compile 'org.springframework.boot:spring-boot-starter-web'
// Remove Tomcat (included in -web) and include Jetty instead
providedRuntime 'org.springframework.boot:spring-boot-starter-jetty'
// Other Spring modules
compile 'org.springframework.boot:spring-boot-starter-social-facebook'
compile 'org.springframework.boot:spring-boot-starter-social-linkedin'
compile 'org.springframework.social:spring-social-google:1.0.0.RELEASE'
compile 'org.springframework.boot:spring-boot-starter-thymeleaf'
compile 'org.springframework.boot:spring-boot-starter-security'
compile 'org.springframework.boot:spring-boot-starter-actuator'
compile 'org.springframework.boot:spring-boot-devtools'
compile 'org.springframework:spring-context'
compile 'org.springframework:spring-context-support'
}
configurations {
providedRuntime.exclude group: 'org.springframework.boot', module:'spring-boot-starter-tomcat'
all*.exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging' // exclude when using log4j
}
springBoot {
mainClass = 'rs.web.Weblication'
executable = true
}
bootRun {
addResources = true
}
processResources {
// exclude resources if they look like they're profile dependent but don't match the current env/profile
eachFile { d ->
if(d.name.endsWith('.xml') || d.name.endsWith('.yaml') || d.name.endsWith('.properties')) {
//def fname = d.name.replaceFirst(~/\.[^\.]+$/, '')
//if(fname.indexOf("-") > -1 && ! fname.endsWith("-" + environment)) {
// d.exclude()
//} else {
// replace #variables# listed below in properties/config files
filter(org.apache.tools.ant.filters.ReplaceTokens, tokens: [
activeProfiles: environment
])
//}
}
}
}
war {
baseName = 'project-web'
version = '1.0.0'
manifest {
attributes 'Implementation-Title': baseName,
'Implementation-Version': version
}
webXml = file('src/main/resources/web.xml')
// rename the war task which has profiles appended from warName-profile,profile2.war
// to warName-profile.profile2.war
classifier = environment.replaceAll(',','-')
}
but when I build it (./gradlew build, or ./gradlew subprojectname:build), all is well and a working WAR is created, but not an executable one.
With a single project, I have it working fine.
Ah ha, right well I build a test multi-project build and it worked OK, so it was clearly the configuration above.
I worked through a process of elimination and it turns out that the problematic area was the line
classifier = environment.replaceAll(',','-')
which is intended to rename files with environment variables as part of the name. This process seems to get in the way of the script addition; perhaps it could be applied afterwards if it's really necessary.

Bundling all dependencies in .aar file

I have an SDK project that is referencing quit alot of dependencies in gradle. I have to ask the SDK users to add those dependencies when they use the SDK in their projects. The problem is, every time I add some new dependency or replace current dependency with a new one, I'll have to ask the users to make changes as well, which is not a good practice in my opinion. Is there a way to bundle all the dependencies in the .aar. I am generating the artifact file with the following code.
uploadArchives{
repositories.mavenDeployer {
def deployPath = file(getProperty('aar.deployPath'))
repository(url: "file://${deployPath.absolutePath}")
pom.project {
groupId 'myPackageName'
artifactId 'wingoku-io'
version "0.0.6"
}
}
These are my dependencies:
dependencies {
compile 'com.github.nkzawa:socket.io-client:0.5.0'
compile 'com.android.support:cardview-v7:21.+'
compile 'de.greenrobot:eventbus:2.4.0'
}
EDIT:
I have added the following method in uploadArchives method. The size of the artifact file has increased but when I use the .aar file in app project, it can't find the files.
uploadArchives{
repositories.mavenDeployer {
def deployPath = file(getProperty('aar.deployPath'))
repository(url: "file://${deployPath.absolutePath}")
pom.project {
groupId 'myPackageName'
artifactId 'wingoku-io'
version "0.0.6"
}
**configurations.all {
transitive = true
}**
}
UPDATE:
I tried the following code because #aar was generating errors (couldn't find xx.xx.xx.aar on jcenter()). This still fails, the d
compile ('com.github.nkzawa:socket.io-client:0.5.0'){
transitive=true
}
compile ('com.android.support:cardview-v7:21.+#aar'){
transitive=true
}
compile ('de.greenrobot:eventbus:2.4.0'){
transitive=true
}
Dalvik throws following warnings for all classes:
dalvikvm﹕ Link of class 'Lio/wingoku/sdk/Fetch$6;' failed
It eventually throws exception ClassDefNotFound
Regarding your edit
configurations.all {
transitive = true
}
I'm not sure it as any effect.
I think you should write something like this:
dependencies {
compile 'com.github.nkzawa:socket.io-client:0.5.0'{
transitive=true
}
compile 'com.android.support:cardview-v7:21.+#aar'{
transitive=true
}
compile 'de.greenrobot:eventbus:2.4.0'{
transitive=true
}
}
It just say that
cardview is aar to include in this library.
eventbus and socket.io-client are jar lib to include in aar

How to exclude dependencies in the POM file generated by the Gradle

I'm using the "maven" plugin to upload the artifacts created by Gradle build to Maven central repository. I'm using a task similar to the following one:
uploadArchives {
repositories {
mavenDeployer {
beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
pom.project {
name 'Example Application'
packaging 'jar'
url 'http://www.example.com/example-application'
scm {
connection 'scm:svn:http://foo.googlecode.com/svn/trunk/'
url 'http://foo.googlecode.com/svn/trunk/'
}
licenses {
license {
name 'The Apache License, Version 2.0'
url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
}
}
}
}
}
}
However the POM file created by this task does not report correctly the dependencies that have been excluded in my Gradle build file. For example:
dependencies {
compile('org.eclipse.jgit:org.eclipse.jgit.java7:3.5.2.201411120430-r') { exclude module: 'commons-logging' }
compile('com.upplication:s3fs:0.2.8') { exclude module: 'commons-logging' }
}
How to have excluded dependencies managed correctly in the resulting POM file?
You can simply override the dependencies of the pom by filtering out the unwanted dependencies, e.g. to exclude junit you can add the following lines to the mavenDeployer configuration:
pom.whenConfigured {
p -> p.dependencies = p.dependencies.findAll {
dep -> dep.artifactId != "junit"
}
}
The problem was that in the exclude definition was not specified the group but only the module.
Adding the both of them the exclusions are added correctly in the POM file. For example:
compile('org.eclipse.jgit:org.eclipse.jgit.java7:3.5.2.201411120430-r') {
exclude group: 'commons-logging', module: 'commons-logging'
}
compile('com.upplication:s3fs:0.2.8') {
exclude group: 'commons-logging', module: 'commons-logging'
}
Using 'exclude' on a Gradle dependency is normally the correct answer, but I still needed to remove some of my "runtimeOnly" dependencies from the POM that led me to this StackOverflow page. My testing using Gradle 4.7 seems to show that using "compileOnly" leaves the dependency out of the pom entirely, but "runtimeOnly" adds a "runtime" dependency in the pom, which in my case, is not what I wanted. I couldn't figure out a "standard" Gradle way of leaving runtime dependencies out of the POM.
The pom.whenConfigured method shown in another answer works for legacy "maven" plugin publishing, but doesn't work for the newer "maven-publish" plugin. My experimentation led to this for "maven-publish":
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
pom.withXml {
asNode().dependencies.dependency.each { dep ->
if(dep.artifactId.last().value().last() in ["log4j", "slf4j-log4j12"]) {
assert dep.parent().remove(dep)
}
}
}
}
}
}

How to resolve a dependency extension within a Gradle build script

I'm using the maven-publish plugin in my build.gradle. For each of the compile dependencies, the group, name and version are used to generate the appropriate tags in the generated pom.xml file - and this works fine.
Here are the example dependencies I have:
dependencies {
compile (
[group: 'com.actionbarsherlock', name: 'actionbarsherlock', version: '4.4.0', ext: 'aar'],
[group: 'com.android.support', name: 'support-v4', version: '19.0.+']
)}
Here is the publishing element I have:
publishing {
publications {
// A publication named 'mavenAndroid'
mavenPublishLibrary(MavenPublication) {
// Artifact using the aar from the build output
artifact "${project.projectDir}/build/outputs/aar/${project.name}-${project.version}.aar"
// Generate dependencies manually for POM
pom.withXml {
def dependenciesNode = asNode().appendNode('dependencies')
//Iterate over the compile dependencies, adding a <dependency> node for each
configurations.compile.allDependencies.each {
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', it.group)
dependencyNode.appendNode('artifactId', it.name)
dependencyNode.appendNode('version', it.version)
// This is what I'd want to do...
if (it.ext != '') {
dependencyNode.appendNode('type', it.ext)
}
// ...but this doesn't work!
}
}
}
}
}
I'd like to be able to add the ext value (e.g. aar) to the pom.xml along with the group, name and version, something like what I have in the above snippet.
I ask these questions when I've been struggling for hours, and then I always seem to answer myself soon after asking it!
I used the following to get the dependency extension, replacing the if() in the question:
it.getArtifacts().each {
dependencyNode.appendNode('type', it.getExtension())
}

Resources