Gradle remove specific dependency configuration from generated pom - gradle

I need to ignore some dependencies defined in the configuration "configurations.nonDistributable" when using gradles plugin maven-publish to generate pom files, I haven't found a reliable way of doing this, except for manually parsing the XML to remove them. Am I missing something, does gradle allow for an easier way of doing this?
build.gradle example:
configurations{
nonDistributable
}
dependencies {
nonDistributable ('org.seleniumhq.selenium:selenium-java:2.52.0'){
exclude group:'com.google.guava' // included in elasticsearch
}
nonDistributable ('com.assertthat:selenium-shutterbug:0.3') {
transitive = false
}
nonDistributable 'mysql:mysql-connector-java:5.1.40'
nonDistributable fileTree(dir: 'non-distributable-libs', include: '*.jar')
}
// generate subprojects pom
subprojects {
apply plugin: 'maven-publish'
model {
tasks.generatePomFileForMavenJavaPublication {
destination = file("$buildDir/../../$distDir/build/pom/$project.name-pom.xml")
}
}
afterEvaluate { project ->
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
}
}
}
}
}
// generate root project pom
model {
tasks.generatePomFileForMavenJavaPublication {
destination = file("$buildDir/../$distDir/build/pom/$project.name-pom.xml")
}
}
afterEvaluate { project ->
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
}
}
}
}

You can create your own publication pom. It would look something like this:
customMaven(MavenPublication) {
artifactId 'myArtifactId'
pom.withXml {
def dependencies = asNode().appendNode('dependencies')
configurations.specialConfiguration.getResolvedConfiguration().getFirstLevelModuleDependencies().each {
def dependency = dependencies.appendNode('dependency')
dependency.appendNode('groupId', it.moduleGroup)
dependency.appendNode('artifactId', it.moduleName)
dependency.appendNode('version', it.moduleVersion)
}
}
}
Then you can create a special configuration that extends from only those configurations that you want to include.
I am using this to create a special pom that contains all testRuntime dependencies to be used for integration tests separated from the main project.

Related

Generate a shadow jar by feature, with Gradle in a Java project

I try to use the java plugin feature (https://docs.gradle.org/5.3-rc-1/userguide/feature_variants.html) to declare 2 versions of the same dependency, and generate at the end, 2 jars:
java {
registerFeature('v1') {
usingSourceSet(sourceSets.main)
}
registerFeature('v2') {
usingSourceSet(sourceSets.main)
}
}
dependencies {
compileOnly project(':djobi-core')
v1Implementation(group: 'org.elasticsearch', name: 'elasticsearch-spark-13_' + scalaVersion, version:'6.2.2') {
exclude group: "org.scala-lang"
}
v2Implementation(group: 'org.elasticsearch', name: 'elasticsearch-spark-13_' + scalaVersion, version:'6.3.2') {
exclude group: "org.scala-lang"
}
}
ShadowJar {
}
But it generates only 1, is it a good way to use feature feature like this?
The default task shadowJar uses the runtime configuration, see the docs-
In order to shadow configurations v1 and v2 we can define two new tasks, of type ShadowJar (they need to be configured).
Actually, v1 and v2 could be defined as "normal" configurations, that is, avoiding to use the feature-variants (it is simpler; moreover when trying to use shadowJar and the v1Implementation above, we have an error (Resolving configuration 'v1Implementation' directly is not allowed).
See the edited example below; it can be built with gradle shadowJar1 shadowJar2.
buildscript {
repositories {
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
classpath "com.github.jengelman.gradle.plugins:shadow:5.0.0"
}
}
apply plugin: "com.github.johnrengelman.shadow"
apply plugin: 'java'
repositories {
maven {
url "https://plugins.gradle.org/m2/"
}
mavenCentral()
}
configurations {
v1 {
extendsFrom(implementation)
}
v2 {
extendsFrom(implementation)
}
}
dependencies {
// tweaking deps here
v1('ant:ant:1.6')
v2('junit:junit:4.12')
}
task shadowJar1(type: com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar ) {
classifier = 'v1'
configurations=[project.configurations.v1]
}
task shadowJar2(type: com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar ) {
classifier = 'v2'
configurations=[project.configurations.v2]
}

Define the generator code location using gradle to build xtext and xtend

I'm trying to create a first project using xText and xTend building with gradle.
I created the grammar following the guidance in the xText documentation and also created the xtend generators.
In eclipse the code generates to src-gen folder as expected.
When I created the gradle script, also following the http://xtext.github.io/xtext-gradle-plugin/xtext-builder.html to build my code instead of generating the code in 'src-gen' folder it generates in 'build' folder.
Is there any way to change this folder from build to src-gen in the gradle? I tried a lot of things and I got always errors.
Complete code of grade script:
apply plugin: 'org.xtext.builder'
dependencies {
xtextLanguages 'com.example.mylang:mylang:1.0.0-SNAPSHOT'
}
xtext {
languages {
mylang{
setup = 'com.example.MyLangStandaloneSetup'
generator.outlet.producesJava = true
}
}
sourceSets {
main {
srcDir 'src/main/xtext'
xtendOutputDir 'src-gen'
}
}
}
you can configure that in the source set
sourceSets {
main.xtendOutputDir = 'xtend-gen'
}
e.g.
plugins {
id "org.xtext.xtend" version "1.0.21"
}
apply plugin: 'java'
apply plugin: 'org.xtext.xtend'
sourceSets {
main.java.srcDirs = ['src','xtend-gen']
main.xtendOutputDir = 'xtend-gen'
}
repositories {
jcenter()
}
dependencies {
// This dependency is exported to consumers, that is to say found on their compile classpath.
compile 'org.eclipse.xtext:org.eclipse.xtext.xbase.lib:2.13.0'
}
or for the xtxt builder plugin
buildscript {
repositories {
mavenLocal()
jcenter()
}
dependencies {
classpath 'org.xtext:xtext-gradle-plugin:1.0.21'
}
}
plugins {
id "org.xtext.builder" version "1.0.21"
}
repositories {
mavenLocal()
jcenter()
}
dependencies {
xtextLanguages 'org.xtext.example.mydslfoo:org.xtext.example.mydslfoo:1.0.0-SNAPSHOT'
}
xtext {
version '2.13.0'
languages {
mydslfoo {
setup = 'org.xtext.example.mydslfoo.MyDslFooStandaloneSetup'
generator {
outlets {
HEROES {
}
}
}
}
}
sourceSets {
main {
srcDir 'src'
output {
dir(xtext.languages.mydslfoo.generator.outlet, 'src-gen')
}
}
}
}

Using gradle project variable in buildscript scope

There is a similar question here Access project extra properties in buildscript closure
but i found a "workaround" which does not look like the optimum
I have a multi gradle project - im declaring the repository in the main gradle file
using
subprojects {
repostiories {
maven {..}
}
}
now i also have to set these for the build script because im using a plugin !
so again buildscript { repositories ...
Now instead of pasting the URLs twice i wanted to use a property - as i figured project.ext properties are not set during the buildscript stage thus i put them
in my gradle.settings file
i couldnt set rootProject.ext.xx settings so i had to use
gradle.ext {
mavenURLs = [ companyURL1, companyURL2 ... etc]
}
Now i could use gradle.ext.mavenURLs in my build.gradle file
Is there a better way ?
Is there a way to set the buildscript and dependency repositories for all project in one block without repeating once for buildscript and once for the dependency ?
def repoClosure = { RepositoryHandler repoHandler ->
repoHandler.mavenLocal()
repoHandler.mavenCentral()
['http://mycompany/repo1', 'http://mycompany/repo2'].each { mavenURL ->
repoHandler.maven {
url mavenURL
credentials {
username 'foo'
password 'bar'
}
}
}
}
project.with {
allprojects {
repoClosure(buildscript.repositories)
repoClosure(repositories)
}
}
Simply create my-repositories.gradle file, with content like:
def repoClosure = {
maven {
url uri("${rootProject.rootDir}/offline-repository")
}
google()
mavenCentral()
['http://mycompany/repo1', 'http://mycompany/repo2'].each { mavenURL ->
maven {
url mavenURL
credentials {
username 'my-name'
password 'my-password'
}
}
}
}
project.with {
allprojects {
buildscript {
ext.myVariable = "Just an example!"
repositories(repoClosure)
}
repositories(repoClosure)
}
}
Then in your build.gradle apply it, like:
buildscript {
apply from: './my-repositories.gradle'
ext {
kotlin_version = '1.5.30'
}
dependencies {
classpath 'com.android.tools.build:gradle:7.0.4'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
// ...

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)
}
}
}
}
}
}

Publishing both jar and sources jar to Artifactory from Gradle

Here is my build.gradle:
buildscript {
repositories {
maven {
url 'http://localhost:8081/artifactory/plugins-release'
credentials {
username = "admin"
password = "password"
}
name = "maven-main-cache"
}
}
dependencies {
classpath "org.jfrog.buildinfo:build-info-extractor-gradle:3.0.1"
}
}
apply plugin: 'groovy'
apply plugin: 'maven'
apply plugin: 'codenarc'
apply plugin: 'maven-publish'
apply plugin: "com.jfrog.artifactory"
version="0.0.2"
group = "mylib"
repositories {
mavenCentral()
add buildscript.repositories.getByName("maven-main-cache")
maven {
url "http://localhost:8081/artifactory/myapp-snapshots"
}
}
dependencies {
compile 'commons-validator:commons-validator:1.4.0'
testCompile 'junit:junit:4.11'
}
artifactory {
contextUrl = "http://localhost:8081/artifactory"
publish {
repository {
repoKey = 'myorg-snapshots'
username = "admin"
password = "password"
maven = true
}
defaults {
publications ('mavenJava')
}
}
}
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
}
}
}
task sourcesJar(type: Jar, dependsOn: classes) {
classifier = 'sources'
from sourceSets.main.allSource
}
artifacts {
archives sourcesJar
}
task dist(type: Zip, dependsOn: build) {
classifier = 'buildreport'
from('build/test-results') {
include '*.xml'
into 'tests'
}
from('build/reports/codenarc') {
into 'reports'
}
from('build/docs') {
into 'api'
}
from(sourcesJar) {
into 'source'
}
from('build/libs') {
exclude '*-sources.jar'
into 'bin'
}
}
Based on this current setup:
To build my JAR I have to run gradle clean build groovydoc sourcesJar dist and then
To publish to Artifactory, I have to run a second command of gradle artifactoryPublish
Two things I'm looking to change here:
gradle artifactoryPublish only publishes my built JAR and a dynamically-created POM to Artifactory. I'd like it to also publish the sources JAR that my build is creating. How?; and
Ideally I'd like to be able to do all of the above by just invoking gradle publish instead of having to run the 2 commands sequentially. Is this possible? If so, how?
When it comes to publishing source you need to modify your script in the following way:
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
artifact (sourcesJar) {
classifier = 'sources'
}
}
}
}
When it comes to a single command what you need to do is to define dependencies between tasks. Unfortunately I can't try the script so it may be redundant but should do the job:
artifactoryPublish.dependsOn('clean', 'build', 'groovydoc', 'sourcesJar', 'dist')
publish.dependsOn(artifactoryPublish)

Resources