Override Extra Properties in applied script in gradle - groovy

I have a parent gradle script with some common configuration, but I need to override some values. For this values I define extra properties. Next, in a project I apply the parent file, but I'm not able to override the the value. Here is what I try to do, but id doesn't work.
Parent gradle script (parent.gradle)
apply plugin: 'maven'
ext {
artifact = "test"
}
uploadArchives {
repositories.mavenDeployer {
repository(url: 'someUrl') {
authentication(userName: 'username', password: 'password')
}
pom.project {
artifactId artifact
}
}
}
Project gradle script (build.gradle)
apply from: 'parent.gradle'
ext {
artifact = "parent-gradle"
}
...
In the documentation I did not find any reference on how to do this.
Any idea on how I can do this?

Thanks Peter. Moving the ext statement before apply in the build.gradle, and removing it from parent.gradle solved my problem.

Related

How to configure all subprojects that are using NodePlugin in Gradle

I have a multi-project, and a few of its subprojects use the Gradle Plugin for Node.
./subproject/build.gradle:
// GitHub: https://github.com/node-gradle/gradle-node-plugin
plugins {
id "com.github.node-gradle.node" version "3.4.0"
}
// ...
I would now like to configure all of these subprojects from the root build.gradle.
./build.gradle
pluginManager.withPlugin('what.do.i.put.here') {
node {
download = true
}
// ...
}
Now my question: What do I have to put in as parameter for withPlugin? Where do I find the "official" plugin name to use?
Instead of using the pluginManager I found the following way to achieve this:
// This is executed on all subprojects
subprojects {
// This is executed on all subprojects that use the NodeJS plugin (https://github.com/node-gradle/gradle-node-plugin - npm_<...> (e.g., npm_install))
plugins.withId('com.github.node-gradle.node') {
node {
download = true
}
It uses plugins.withId inside of subprojects, using the ID also specified in the plugins section: com.github.node-gradle.node

Gradle Download And Unzip Multiple Dependencies

I have a generic Artifatory repo that contains some zip files that I need to download and extract in an Android Studio project. I am new to Gradle but found that using an Ivy repository object maybe the best way to do this instead of just downloading the files using a Gradle task which calls curl.
I have managed to get a single zip file downloaded and extracted but soon as I try to add another dependency it overwrites my configuration. See the dependencies block in the code below.
Why is it not adding another dependency and is there a better way to do this?
app:build.gradle:
repositories {
ivy {
url property("artifactoryUrl")
credentials {
username property("artifactoryUser")
password property("artifactoryPassword")
}
authentication {
basic(BasicAuthentication)
}
patternLayout {
artifact '/[organisation]/[module]/third-party/[revision](.[ext])'
}
metadataSources {
artifact()
}
}
}
configurations {
thirdPartyDependencies
}
dependencies {
thirdPartyDependencies "artifactory:test-generic:FreeImage#zip"
thirdPartyDependencies "artifactory:test-generic:GLEW#zip" // thirdPartyDependencies has been overwritten
}
task CopyThirdPartyDependencies(type: Copy) {
def thirdPartyDirectory = getProject().getRootDir().toString() + "/third-party/"
println(configurations.thirdPartyDependencies.resolvedConfiguration.resolvedArtifacts)
configurations.thirdPartyDependencies.resolvedConfiguration.resolvedArtifacts.each { artifact ->
copy {
from zipTree(artifact.getFile())
into thirdPartyDirectory
}
}
}
preBuild.dependsOn(CopyThirdPartyDependencies)

Why do I get a "connot be applied to 'Closure'" Warning in my gradle script?

I have a hard time figuring out, why IntelliJ warns me about this part in my build.gradle file:
apply plugin: 'distribution'
(...)
distributions {
main {
baseName = 'someName'
contents {
from { 'src/readme' }
}
}
}
shot:
I took it straight from the gradle user guide and the build seems to work ok. So, is this a false positive or should I take this serious? If so, what's the problem here and how would one check the API / code to find the expected types and so on?
it is a false positive, but if you want to make it disappear use the following
apply plugin: 'distribution'
distributions.create('someNameButMain', {
baseName = 'someName'
contents {
from { 'src/readme' }
}
})

publish artifact overwrite other artifact in Gradle

I am experimenting with Gradle to build a few jars, rather than maintain a list of classes that hold EJBs so that I can deploy them separately I thought it might be neat to scan the classes when making the jar.
Rather than load the classes and use reflection to get the annotations I thought it may be simpler to scan the classes with asm, hence the chuncky ClassReader in one of the tasks.
I don't think this is the issue so can be ignored, basically I have 2 tasks that I use to define the contents of the jars, both report that different content is going into them via the eachFile print out, however when I look in the publish repository location both files and associated sha1 are identical.
Either Gradle is broken or, more likely, I've done something crazy but can't see what it is, can anyone help?
By the way if I disable the publish of either of the jar files the one that does get created is correct so I think it's something wrong with the publish rather than the jarring up, but could be wrong.
// ASM is used to interpret the class files, this avoids having to load all classes in the vm and use reflection
import org.objectweb.asm.*
task ejbJar(type: Jar) {
//outputs.upToDateWhen { false }
from "${project.buildDir}/classes/main"
eachFile { println "EJB server: ${name}" }
include getEjbClassFiles(project.buildDir)
}
task clientEjbJar(type: Jar) {
//outputs.upToDateWhen { false }
from "${project.buildDir}/classes/main/com/company/core/versioner"
eachFile { println "Client EJB ${name}" }
include '**/*'
}
artifacts {
archives clientEjbJar
archives ejbJar
}
String[] getEjbClassFiles(base) {
def includedFiles = []
def baseDir = project.file("${base}/classes/main")
def parentPath = baseDir.toPath()
if (baseDir.isDirectory()) {
baseDir.eachFileRecurse(groovy.io.FileType.FILES) { file ->
if(file.name.endsWith('.class')) {
//get hold of annotations in there --- org.objectweb.asm.Opcodes.ASM4
def reader = new ClassReader(file.bytes).accept(
new ClassVisitor(Opcodes.ASM4) {
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
if(desc.equals("Ljavax/ejb/Stateless;") ||
desc.equals("Ljavax/ejb/Stateful;")) {
includedFiles += parentPath.relativize(file.toPath())
}
return null //no interest in actually visiting the annotation values
}
},
ClassReader.SKIP_DEBUG | ClassReader.EXPAND_FRAMES | ClassReader.SKIP_FRAMES | ClassReader.SKIP_CODE
)
}
}
}
return includedFiles
}
publishing {
publications {
mypub(IvyPublication) {
artifact(ejbJar) {
name 'ejb'
}
artifact(clientEjbJar) {
name 'client-ejb'
}
}
}
repositories {
ivy {
name 'personal'
url "${ant['developer.repository']}/"
layout 'pattern', {
artifact "[organisation]/[module]/[artifact]/[revision]/[type]/[artifact]-[revision].[ext]"
ivy "[organisation]/[module]/[type]/[revision]/[type]/[type]-[revision].[ext]"
}
}
}
}
I did break the thing down into a simpler form as I thought it may be a Gradle bug.
The simplified form was:
apply plugin: 'java'
apply plugin: 'ivy-publish'
task bigJar(type: Jar) {
from "${rootDir}/src/main/resources"
include '**/*'
}
task smallJar(type: Jar) {
from "${rootDir}/src/main/resources/A/B"
include '**/*'
}
group 'ICantBeEmpty'
artifacts {
archives bigJar
archives smallJar
}
publishing {
publications {
mypub(IvyPublication) {
artifact(bigJar) { name 'biggie' }
artifact(smallJar) { name 'smallie' }
}
repositories {
ivy {
name 'personal'
url "c:/temp/gradletest"
layout 'pattern', {
artifact "[organisation]/[module]/[artifact]/[revision]/[type]/[artifact]-[revision].[ext]"
ivy "[organisation]/[module]/[type]/[revision]/[type]/[type]-[revision].[ext]"
}
}
}
}
}
This results in 2 files in c:/temp/gradletest/ICantBeEmpty/report-bug/biggie/unspecified/biggie-unspecified.jar and c:/temp/gradletest/ICantBeEmpty/report-bug/smallie/unspecified/smallie-unspecified.jar
Both of these files are identical, however I think I know why see my later answer.
Whilst looking at some configurations I noticed some odd behaviour that led me to a resolution of this issue, and it is a Gradle bug.
In my build I had a scratch task doing
configurations.archives.artifacts.each { println it }
This gave me 5 different lines output, however changing it to this
configurations.archives.artifacts.each { println it.file }
produced the same filename 5 times.
It turns out this is related to my issue, although the artifacts are there as separate entities the name used to uniquely identify them was the same so the same file was always chosen during a publish. The name of the artifacts is given by ${baseName}-${appendix}-${version}-${classifier}.${extension} by default in the java plugin. This means that if neither appendix or classifier is specified then the artifact will have the same name.
I tested this using the above sample code by adding an appendix name
task bigJar(type: Jar) {
appendix = 'big'
from "${rootDir}/src/main/resources"
include '**/*'
}
task smallJar(type: Jar) {
appendix = 'small'
from "${rootDir}/src/main/resources/A/B"
include '**/*'
}
Using this rather than the code from the question produces 2 different jars.
It's not a complete answer but is a good enough work around, if I add a new publication definition I can publish the artifacts that I want to to the location that I want, the only downside is that it will create another gradle task which isn't ideal.
publications {
mypub(IvyPublication) {
artifact(ejbJar) {
name 'ejb'
}
}
newpub(IvyPublication) {
artifact(clientEjbJar) {
name 'client-ejb'
}
}
}
The above answer works in the short term, however does reveal yet another short coming in the Gradle world enter link description here
Not sure Gradle is all it could be at the moment, and so far no one has answered my questions so maybe it's not that actively developed!!
I'm no expert in this part of Gradle, but the functionality you are using is marked as "incubating"; you are using the new publishing feature which might or might not be complete. Perhaps you should use the old way of doing things. You also seem to be mixing both ways by using the artifacts closure.

Apply configuration to specific projects in gradle build script

I have a gradle project that has java applications as well as android applications.
root/
build.gradle
settings.gradle
java1/
java2/
android1/
android2/
java3/
etc.
What is the best practice for structuring my build script? I am a total gradle novice and am migrating the project from maven to gradle.
I wanted to do something instead of
configure(subprojects) {}
to apply plugins and other specific things.
such as
configure(java1, java2, java3) { // java specifics }
configure(android1, android2) { // android specifics }
I am probably approaching this from the wrong way.
More explicitly I need to apply the plugin java only for the java projects and the android plugin for the android projects.
configure(subprojects.findAll {it.name == "java1" || it.name == "java2"}) {
Under the filtering section in the guide
Hope this helps someone else out.
There are multiple ways, depending on what you want... Some examples:
// Configures just project java1
project(":java1") { ... }
// Configures projects java1 and java2
["java1","java2"].each { name ->
project(":$name") { ... }
}
You can use normal groovy to find/iterate over all the projects.
Another option:
configure([ project(':sub1'), project(':sub2'), ... ]) {
...
}
The shortest and easiest option:
configure(subprojects.findAll()) {
if (it.name.equals('MY_PROJECT')) {
...
} else {
...
}
}
Another approach...
In the settings.gradle you do define your projects like this:
gradle.ext.javaProjects=[]
gradle.ext.androidProjects=[]
javaProject('java1')
javaProject('java2')
javaProject('java3')
androidProject('android1')
androidProject('android2')
def javaProject(String name) {
gradle.ext.javaProjects.add(name)
include ":$name"
}
def androidProject(String name) {
gradle.ext.androidProjects.add(name)
include ":$name"
}
Now you can reference those in your root build.gradle:
def javaProjects = subprojects.findAll {gradle.ext.javaProjects.contains(it.name)};
def androidProjects = subprojects.findAll {gradle.ext.javaProjects.contains(it.name)};
configure(javaProjects) {
...
}
configure(androidProjects) {
...
}
Maybe thats overkill... but i usually have the project definition method in my settings.gradle anyway. E.g. if you want to put all java projects under a java folder you could define things like this:
def javaProject(String name) {
gradle.ext.javaProjects.add(name)
include ":$name"
project(":$name").projectDir = file('java/'+ name)
}

Resources