Is there a simple way to configure a Gradle plugin immediately if it exists or later if it's added? - gradle

I sometimes use apply from: 'some/common/config.gradle' and would like an easy way to configure a related plugin immediately if it already exists or to watch for it to be added and configure it later. I can do what I want, but it seems a bit messy since I end up copy / pasting the config into two spots. The below does what I want, but I'm wondering if there's a better way.
def configured = false;
if(plugins.hasPlugin(ApplicationPlugin)) {
run.classpath.add(configurations.jfxrt)
startScripts {
mainClassName = "com.javafx.main.Main"
doLast {
logger.warn(":${project.name}:startScripts:!! WARNING !!" +
" Replaced mainClassName with com.javafx.main.Main")
}
}
configured = true
}
else {
plugins.whenPluginAdded { plugin ->
if(plugins.hasPlugin(ApplicationPlugin) && !configured) {
run.classpath.add(configurations.jfxrt)
startScripts {
mainClassName = "com.javafx.main.Main"
doLast {
logger.warn(":${project.name}:startScripts:!! WARNING !!" +
" Replaced mainClassName with com.javafx.main.Main")
}
}
configured = true
}
}
}

The way to achieve this is plugins.withType(ApplicationPlugin) { ... }.

Related

How can I invoke Gradle's repository search manually?

As a precondition for building a release version, say acme-widgets-1.0, I would like to search the configured repositories (or a specific repository) to make sure acme-widgets-1.0.jar hasn't already been published. How can I do this with Gradle? Alternatively, is there a way to configure a not-exists dependency for a specific version?
group = 'com.acme'
version = '1.0'
repositories {
jcenter()
}
if (gradle.startParameter.taskNames.contains("release")) {
def taskNames = gradle.startParameter.taskNames
taskNames.add(0, "checkReleaseDoesntExist")
gradle.startParameter.taskNames = taskNames
}
task checkReleaseDoesntExist() {
}
task release() {
println "Building release"
}
checkReleaseDoesntExist.doLast {
println "Checking repositories to make sure release hasn't already been built"
// TODO What do I do here?
}
You could declare a configuration with only the artifacts for which you are trying to see if they are already published.
Upon resolving this configuration, you would have an empty fileset or not.
So something along the lines of:
configurations {
checkRelease { transitive = false }
}
dependency {
checkRelease "$group:$name:$version"
}
task ('checkReleaseDoesntExist') {
doLast {
println "Checking repositories to make sure release hasn't already been built"
try {
if (!configurations.checkRelease.files.isEmpty()) {
// already exists
}
}
catch (ResolveException e) {
// doesn't exist
}
}

How do I get IntelliJ to recognize gradle generated sources dir?

So I have an XJC javaExec that spins like a top but IntelliJ doesn't recognize the generated output despite having marked generated-src/java as such. Do I need to tweak the idea plug-in or something?
Note: The plug-in itself is loaded in subProjects from the root build.gradle.
XJC Project:
description = "Generates sources and compiles them into a Jar for $project"
configurations { xjc }
dependencies {
xjc 'org.glassfish.jaxb:jaxb-xjc:2.2.11'
xjc 'org.glassfish.jaxb:jaxb-runtime:2.2.11'
}
task xjc (type:JavaExec) {
doFirst{
File generatedSrcDir = file("$buildDir/generated-src/java")
if (!generatedSrcDir.exists()) {
generatedSrcDir.mkdirs()
}
}
main = "com.sun.tools.xjc.XJCFacade"
classpath configurations.xjc
def argsList = [
"-mark-generated",
"-no-header",
"-verbose", // or -quiet or nothing for default.
"-target", "2.1",
"-encoding", "UTF-8",
"-d", "$buildDir/generated-src/java",
"-catalog","$projectDir/src/main/resources/commons-gradle.cat",
file("$projectDir/src/main/resources/v1/") ]
args argsList
inputs.files files(file("$projectDir/src/main/resources/v1/"))
outputs.files files(file("$buildDir/generated-src/java"),file("$buildDir/classes"))
}
compileJava {
dependsOn xjc
source "${buildDir}/generated-src"
}
In the project that depends on this one I simply have:
compile project(":path:to:schemas:the-test-schema")
I've tried:
idea {
module {
def buildDir = file("$buildDir")
def generatedDir = file("$buildDir/generated-src")
def listOfDirs = []
buildDir.eachDir { file ->
if (file.name != buildDir.name && file.name != generatedDir.name)
listOfDirs.add(file)
}
excludeDirs = listOfDirs.toArray()
generatedSourceDirs += file("$buildDir/generated-src/java")
scopes.COMPILE.plus += [ configurations.xjc ]
}
}
I'll point out a solution by Daniel Dekany, from a Gradle discussion thread actually linking to this question. To quote:
apply plugin: "idea"
...
sourceSets.main.java.srcDir new File(buildDir, 'generated/javacc')
idea {
module {
// Marks the already(!) added srcDir as "generated"
generatedSourceDirs += file('build/generated/javacc')
}
}
Works well for me.
The code of this answer, rewritten using Kotlin DSL, will look like this:
plugins {
idea
}
val generatedSourcesPath = file("out/production/classes/generated")
java.sourceSets["main"].java.srcDir(generatedSourcesPath)
idea {
module {
generatedSourceDirs.add(generatedSourcesPath)
}
}
In my case, it didn't work unless I added the generate sources directory to both sourceDirs and generatedSourceDirs:
def generatedSourcesDir = file('src/generated/main/java')
idea {
module {
sourceDirs += generatedSourcesDir
generatedSourceDirs += generatedSourcesDir
}
}
in 2020 you probably did not refresh the project in IDEA
because it actually works oob.
30 mins of reading outdated solutions :(
It's happening in some versions. There are some issues that we can look at and read carefully.
But for myself, from the IntelliJ IDEA 2019 the solutions below aren't working anymore:
https://youtrack.jetbrains.com/issue/IDEA-210065 (it says Obsolete)
https://youtrack.jetbrains.com/issue/IDEA-152581 (it's saying Fixed here)
https://youtrack.jetbrains.com/issue/IDEA-117540/generated-sources-inside-output-directory-are-excluded-by-default
https://intellij-support.jetbrains.com/hc/en-us/community/posts/4906059373074-Class-defined-in-generated-sources-not-found-by-Intellij-editor-but-found-by-compiler-gradle-build-
Discussion in the Gradle forum about this: https://discuss.gradle.org/t/how-do-i-get-intellij-to-recognize-gradle-generated-sources-dir/16847
According to #Daniel Dekany, this worked in IDEA 2017.1.2, and worked for me until 2019:
plugins {
id 'idea'
}
idea {
module {
generatedSourceDirs += file('build/generated/sources/annotationProcessor')
}
}
But from 2019 to 2022, the solution that worked for me was:
def generatedDir = "${buildDir}/generated/sources"
sourceSets {
main {
java {
srcDir generatedDir
}
}
}
idea {
module {
generatedSourceDirs.addAll(file(generatedDir))
}
}
ext {
// path to IDEA generated sources directory
ideaGeneratedSourcesDir = "$projectDir/src/main/generated"
}
compileJava {
//……
options.annotationProcessorGeneratedSourcesDirectory = file(ideaGeneratedSourcesDir)
//options.headerOutputDirectory.set(file(ideaGeneratedSourcesDir)) (tested no effect)
//……
}
// above work for me, and i try all method this question mentioned it's not work! env: idea2019.3, wrapped gradle6.3-all, zh-CN, JDK8, [x] annotation processing is disabled(no effect, in global settings ), no idea plugin([x]plugins {id idea}), [x]sourceSets no need to set(genereated srcDir)
myCodeGenExample:
task vertxCodeGen(type: JavaCompile) {
group 'build'
source = sourceSets.main.java
destinationDir = file(ideaGeneratedSourcesDir)
classpath = configurations.compileClasspath
options.annotationProcessorPath = configurations.annotationProcessor
options.debugOptions.debugLevel = "source,lines,vars"
options.compilerArgs = [
"-proc:only",
"-processor", "io.vertx.codegen.CodeGenProcessor",
// where the non Java classes / non resources are stored (mandatory) - the processors requires this option to know where to place them
"-Acodegen.output=$destinationDir.absolutePath",
]
}
refresh the gradle, continously exist

Communication between gradle methods and tasks

I can't seem to get my collection from the method to a state where generateWadleTasks can iterate over it. At least not in a way such that I can access it. I've tried properties, parameters and return values. What's wrong with this picture? I seem to have some misconceptions about how information is passed around either in Groovy or in Gradle... or perhaps both. An explanation of the scopes involved might help. This is a subproject.
buildscript{
...
}
ext.collectionOfObjects = []
class WadleProfile {
def File wadleFile;
def wadlArgs;
}
ext.factoryMethod = {
//supposed to create and add WadleProfiles to collectionOfWadleProfiles
}
compileJava {
doFirst { factoryMethod() }
}
task generateWadlTasks {
println "Executing generateWadlTasks"
project.ext.collectionOfObjects.each { wadlProfile ->
task("wadl2java" + wadlProfile.id, type: JavaExec, dependsOn: 'classes') {
main = project.wadlBaseMain
...
}
}
}

(No such file or directory) how to make non existant file to be ignored by gradle

when i run the command 'gradle tasks' or anything for that fact, i got the following error:
Caused by: java.io.FileNotFoundException: /Users/maxit/workspace/Backbone/modules/contact-form/public/build/contact-src.js (No such file or directory)
Here is my gradle build file:
configurations {
sshAntTask
}
dependencies {
sshAntTask 'org.apache.ant:ant-jsch:1.7.1', 'jsch:jsch:0.1.29'
}
// Pull the plugin from Maven Central
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.eriwen:gradle-js-plugin:1.5.0'
}
}
// Invoke the plugin
apply plugin: 'js'
apply plugin:'base'
def appName = "some"
def version = "0.0.1"
def jsSrcDir = 'public/js'
javascript.source {
dev {
js {
srcDir jsSrcDir
include "*.js"
exclude "*.min.js"
}
}
prod {
js {
srcDir jsSrcDir
include "*.min.js"
}
}
}
task combineSrc(type: com.eriwen.gradle.js.tasks.CombineJsTask) {
source = ["${projectDir}/public/templates/templates.js","${projectDir}/public/js/models/contact_model.js", "${projectDir}/public/js/views/contact_form_view.js", "${projectDir}/public/js/app.js" ]
dest = file("${projectDir}/public/build/${appName}-src.js")
}
task appendJQuery(dependsOn: 'combineSrc') {
String backboneSrc = file(new File("${projectDir}/public/build/${appName}-src.js")).text
new File("${projectDir}/public/build/${appName}-jqueryWraped.js").withWriter{ out ->
out << "(function(\$){" + file("${projectDir}/public/build/${appName}-src.js").text + "})(jQuery); \n"
}
}
It appears, that gradle doesn't ignore a file that is none existant. The task 'combineSrc' hasn't been run, yet to create the file....and i am unable to run the task 'cobineSrc' to create the file in the first place. Its kind a dead end. what am i doing wrong and how to make this work? Thank you
The reason you're failing is, that all the stuff you currently doing during the configuration of the appendJQuery task should be done in the execution phase.
just refactor your appendJQuery task to do:
task appendJQuery(dependsOn: 'combineSrc') {
doLast{
String backboneSrc = file(new File("${projectDir}/public/build/${appName}-src.js")).text
new File("${projectDir}/public/build/${appName}-jqueryWraped.js").withWriter{ out ->
out << "(function(\$){" + file("${projectDir}/public/build/${appName}-src.js").text + "})(jQuery); \n"
}
}
}
hope that helps!
René

Why do different parts of my build scripts see different values for the project.version property?

I do the following in gradle in allprojects section...
if (project.hasProperty('myVersion')) {
project.ext.realVersion = project.myVersion
project.version = project.myVersion
println("project version set")
} else {
project.ext.realVersion = 'Developer-Build'
project.version = 'Developer-Build'
println("project version set to devbuild")
}
Now, I have some code that correctly uses project.version and it works, BUT then there is other code that is ALSO using the same property project.versoin and the result is 'unspecified'. If I change both to project.realVersion, they both work. version seems to be this nasty special property that doesn't always seem to work.
The code using the properties is below....(notice where I use realVersion, version does NOT work, but it works fine in the other location :( )....how weird.
task versionFile() << {
File f = new File('output/version');
f.mkdirs()
File v = new File(f, 'version'+project.ext.realVersion)
println('v='+v.getAbsolutePath())
v.createNewFile()
}
task myZip(type: Zip) {
archiveName 'dashboard-'+project.version+'.zip'
from('..') {
include 'webserver/run*.sh'
include 'webserver/app/**'
include 'webserver/conf/**'
include 'webserver/play-1.2.4/**'
include 'webserver/public/**'
include 'webserver/lib/**'
}
from('output/version') {
include '**'
}
}
myZip.dependsOn('versionFile')
assemble.dependsOn('myZip')
The problem has nothing to do with the version property in particular. Build scripts are evaluated sequentially. If you can't guarantee that you are setting the version property before you are reading it, you have to defer reading the property until the end of the configuration phase. Otherwise you'll inevitably run into problems. One way to do this is to put the configuration code that reads the property into a gradle.projectsEvaluated {} block. task.doFirst {} is another way, but has the limitation that the configured value won't be considered for up-to-date checking.
Sometimes there is an easier solution. For example, in the case of archive tasks like Zip, you can just set baseName and extension instead of archiveName. As always, I encourage you to study the DSL reference.
Place the following in doFirst like below:
allprojects {
doFirst {
if (project.hasProperty('myVersion')) {
project.ext.realVersion = project.myVersion
project.version = project.myVersion
println("project version set")
} else {
project.ext.realVersion = 'Developer-Build'
project.version = 'Developer-Build'
println("project version set to devbuild")
}
}
}

Resources