Gradle Plugin/Task evaluated before build - java

One of my plugins uses the files created by the gradle build of another project.
However gradle evaluates the plugin task before building. Is there a way to make the plugin tasks be created after the build is completed?
EDIT:
Here is the build.gradle
apply plugin: 'confluence-export'
sourceSets {
tools
}
compileToolsJava {
source += sourceSets.main.java
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
dependencies {
toolsCompile files("${System.getProperty('java.home')}/../lib/tools.jar")
}
task generateTagDoc(type: JavaExec) {
classpath = sourceSets.tools.runtimeClasspath
main = 'TagsDocumentation'
outputs.upToDateWhen { false }
}
task generateTypeDoc(type: Javadoc) {
classpath = sourceSets.tools.runtimeClasspath
source = sourceSets.main.allJava
options.docletpath = compileToolsJava.outputs.files.asList()
options.doclet = "ExtractCommentsDoclet"
options.addStringOption("Tags.java")
outputs.upToDateWhen { false }
}
confluence {
spaceKey = *****
exportAll = true
title = *******
exportUser = "******
exportPassword = ******
libraryName = ******
host = ********
}
asciidoctor {
resources {
from(sourceDir) {
include 'img/**'
}
}
}
asciidoctor.dependsOn(generateTagDoc)
generateTagDoc.dependsOn(generateTypeDoc)
generateTypeDoc.dependsOn(compileToolsJava)
So here I want my build to run which will create a folder asciidoc/html5 in the build folder with all my created html pages from my asciidoc files. My plugin goes through each file and creates a task for it and then uploads it to a website. The problem is the plugin task is evaluated before the build so the folder asciidoc/html5 hasn't been created yet. If i add a check to see if the folder has been created it will indeed remove my error however the task will still be empty. This is why i would like to know if there is a way for the plugin tasks to be created after the build is done so that the folder is created.
EDIT 2:
Here is the plugin creation:
class ConfluenceExportPlugin extends ConfluencePluginBase implements Plugin<Project> {
#Override
void apply(Project project) {
def confluenceExtension = project.extensions.create('confluence', ConfluenceExtension)
project.afterEvaluate {
if (confluenceExtension.exportAll) {
def list = []
def dir = new File("${project.buildDir}/asciidoc/html5")
if(dir.exists() && dir.isDirectory())
dir.eachFileRecurse(FileType.FILES) {
if(it.name.endsWith('.html')) {
list.add(it)
}
}
Task mainTask = project.task('confluenceExport')
mainTask.dependsOn("build")
list.each { file ->
def curName = file.name.take(file.name.lastIndexOf('.'))
ConfluenceExportTask subTask = createTask(project, "confluenceExport${curName}", confluenceExtension, file.path, curName)
mainTask.dependsOn(subTask)
}
}
else {
ConfluenceExportTask task = createTask(project, "confluenceExport", confluenceExtension, getManFile(confluenceExtension, project), confluenceExtension.title)
}
}
}
ConfluenceExportTask createTask(Project project, String taskName, def confluenceExtension, manFile, String pageTitle ){
ConfluenceExportTask task = project.task(type: ConfluenceExportTask, taskName)
task.conventionMapping.map "user", { confluenceExtension.user }
task.conventionMapping.map "password", { confluenceExtension.password }
task.conventionMapping.map "spaceKey", { confluenceExtension.spaceKey }
task.conventionMapping.map "manFile", { manFile }
task.conventionMapping.map "pageTitle", { pageTitle }
task
}
String getManFile(ConfluenceExtension configuration, Project project) {
configuration.exportSourceFilePath ?: "${project.buildDir}/asciidoc/html5/${configuration.libraryName}.html"
}
}

Related

How to create environment specific spring boot jar file name with gradle

I have a requirement to create spring boot jar file name based upon the environments. The environment can be dev or prod. When I run with the command gradlew clean build, it generates app-service-0.0.1.SNAPSHOT.jar. As per my requirement, it should be app-service-0.0.1.SNAPSHOT.jar for dev environment and app-service-0.0.1.jar for prod environment. How can I customize the naming of spring boot jar file in gradle? Please help me. I have also tried in the following manner, it did not work.
... other gradle code ....
ext {
isProd = System.properties['env'] == 'prod'
isDev = System.properties['env'] == 'dev'
}
//if (isDev) tasks.withType(jar).all { it.enabled = false }
task dev(type: org.springframework.boot.gradle.tasks.bundling.BootJar) {
baseName = 'custom-spring-boot'
/*
bootJar {
archiveFileName = 'my-awesome-app.jar'
}
*/
}
/*
bootJar {
if (env == 'dev') {
archiveFileName = 'my-awesome-app.jar'
} else {
archiveFileName = 'hati-app.jar'
}
}
*/
tasks.addRule("Pattern: bootJar<ENV>") { String taskName ->
if (taskName.startsWith('bootJar')) {
def env = (taskName - 'bootJar').toLowerCase()
if (env in ['dev', 'prod',]) {
task(taskName, type: bootJar) {
println "Configuring env: $env"
from("src/main/conf/$env") {
into("conf")
}
}
} else {
println "Invalid env: $env, skipping."
}
}
}
I also checked with this SO link

How to combine multiple Javadoc into one using Gradle

This question was answered before but the chosen answer doesn't explain a lot for me on how this is doable on Gradle.
That and the fact that I can't comment on the solution to ask for more info forced me to make this question.
I have a Gradle project that has several modules available and I now want to set up the Javadoc task to combine the Javadoc comments of all the modules into a single location where I could browse it.
How would I now be able to do this using Gradle? I run Gradle 5.5 if the version is of any importance and I have the following things set in the build.gradle file:
allprojects {
ext {
// Convenience method to configure Javadoc
configureJavadoc = { Object jDocConfig ->
jDocConfig.options {
it.author()
it.encoding = 'UTF-8'
it.memberLevel = JavadocMemberLevel.PROTECTED
if (it instanceof StandardJavadocDocletOptions) {
def opt = it as StandardJavadocDocletOptions
opt.links(
"https://docs.example.com/java/"
)
if (JavaVersion.current().isJava9Compatible()) {
opt.addBooleanOption("html5", true)
opt.addStringOption("-release", "8")
}
if (JavaVersion.current().isJava11Compatible()) {
opt.addBooleanOption("-no-module-directories", true)
}
}
}
}
}
}
subprojects {
javadoc {
destinationDir = file("$rootDir/docs/")
configureJavadoc(it)
}
}
I was able to do it with:
def exportedProjects = [
":",
":module-a",
":module-b",
":module-c"
]
task allJavadoc(type: Javadoc) {
source exportedProjects.collect { project(it).sourceSets.main.allJava }
classpath = files(exportedProjects.collect { project(it).sourceSets.main.compileClasspath })
destinationDir = file("${buildDir}/docs/javadoc-all")
}

Assets not being loaded (libGDX)

So I've made a small desktop application in Eclipse (gradle project) based on libGDX. Runs perfectly in Eclipse. When I export as a "runnable JAR file" (with Package required libraries into generated JAR checked) I get a warning: "Fat Jar Export: Could not find class-path entry for 'D:Project TI Helper/core/bin/default/".
Is something missing in the manifest at "Class-Path: ." ?
I have no idea what this is about. But the JAR is certainly not runnable. So I try the command prompt and do "gradle desktop:dist --stacktrace". Then the JAR file seems to be produced without any errors or warnings. So I go to .../desktop/build/libs/ and try to run it with "java -jar desktop-1.0.jar", the texture packer starts packing but fails in the end with this message in the console.
The generated atlas-file IS in the specified location. The textures WERE packed. Why on earth is it not loading the stuff?? Btw, I'm using Java version 1.8.0_241 for both JDK and JRE.
EDIT
So it fails in the Assets class at "TextureAtlas atlas = assets2d.get(Cn.TEXTURES);". Going deeper into the AssetManager
public synchronized <T> T get (String fileName) {
Class<T> type = assetTypes.get(fileName);
if (type == null) throw new GdxRuntimeException("Asset not loaded: " + fileName);
...
So it seems the string provided is not pointing to my atlas-file. Cn.TEXTURES is defined as "../desktop/assets/atlas/textures.atlas". That raises the question: How DO you write the path?
DesktopLauncher.java
public class DesktopLauncher
{
public static boolean rebuildAtlas = true;
public static boolean drawDebugOutline = true;
public static void main (String[] arg)
{
// Build Texture Atlases
if (rebuildAtlas) {
Settings settings = new Settings();
settings.maxWidth = 2048;
settings.maxHeight = 2048;
settings.pot = false;
settings.combineSubdirectories = true;
// Pack images in "textures" folder
TexturePacker.process("assets/textures", "assets/atlas", "textures.atlas");
}
LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
cfg.title = "TI Helper";
cfg.useGL30 = false;
cfg.width = Cn.RESOLUTION_WIDTH;
cfg.height = Cn.RESOLUTION_HEIGHT;
cfg.fullscreen = true;
new LwjglApplication(new TIHelper(), cfg);
}
}
Assets.java
public class Assets implements Disposable, AssetErrorListener
{
public static final String TAG = Assets.class.getName();
public static final Assets instance = new Assets();
// Asset managers
public AssetManager assets2d;
public AssetDeco assetDeco;
public AssetFonts fonts;
public AssetMisc assetMisc;
// General fonts
public static Font not16, not20, not24, dig16;
// Singelton: prevent installation from other classes
private Assets() {}
public void init ()
{
// Init 2D graphics manager
init2DAssetManager();
TextureAtlas atlas = assets2d.get(Cn.TEXTURES);
// Cn.TEXTURES == String TEXTURES = "../desktop/assets/atlas/textures.atlas";
// Create game resource objects
fonts = new AssetFonts();
assetDeco = new AssetDeco(atlas);
assetMisc = new AssetMisc(atlas);
// Create fonts
not16 = new Font(Assets.instance.fonts.notalot_16);
not20 = new Font(Assets.instance.fonts.notalot_20);
not24 = new Font(Assets.instance.fonts.notalot_24);
dig16 = new Font(Assets.instance.fonts.digits_16);
}
private void init2DAssetManager()
{
// Create the manager
assets2d = new AssetManager();
// Set asset manager error handler
assets2d.setErrorListener(this);
// Load texture atlas
assets2d.load(Cn.TEXTURES, TextureAtlas.class);
// Start loading assets and wait until finished
assets2d.finishLoading();
// Prompt output
Gdx.app.debug(TAG, "# of assets loaded: " + assets2d.getAssetNames().size);
for (String a : assets2d.getAssetNames())
Gdx.app.debug(TAG, "asset: " + a);
}
#Override
public void dispose ()
{
assets2d.dispose();
}
public void error (String filename, Class<?> type, Throwable throwable) {
Gdx.app.error(TAG, "Couldn't load asset '" + filename + "'", (Exception)throwable);
}
...
Desktop build.gradle
apply plugin: "java"
sourceCompatibility = 1.8
sourceSets.main.java.srcDirs = [ "src/" ]
sourceSets.main.resources.srcDirs = ["../desktop/assets"]
project.ext.mainClassName = "com.ti.desktop.DesktopLauncher"
project.ext.assetsDir = new File("../desktop/assets")
task run(dependsOn: classes, type: JavaExec) {
main = project.mainClassName
classpath = sourceSets.main.runtimeClasspath
standardInput = System.in
workingDir = project.assetsDir
ignoreExitValue = true
}
task debug(dependsOn: classes, type: JavaExec) {
main = project.mainClassName
classpath = sourceSets.main.runtimeClasspath
standardInput = System.in
workingDir = project.assetsDir
ignoreExitValue = true
debug = true
}
task dist(type: Jar) {
manifest {
attributes 'Main-Class': project.mainClassName
}
dependsOn configurations.runtimeClasspath
from {
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}
with jar
}
dist.dependsOn classes
eclipse.project.name = appName + "-desktop"
Workspace build.gradle
buildscript {
repositories {
mavenLocal()
mavenCentral()
maven { url "https://plugins.gradle.org/m2/" }
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
jcenter()
google()
}
dependencies {
}
}
allprojects {
apply plugin: "eclipse"
version = '1.0'
ext {
appName = "ti-helper"
gdxVersion = '1.9.10'
roboVMVersion = '2.3.8'
box2DLightsVersion = '1.4'
ashleyVersion = '1.7.0'
aiVersion = '1.8.0'
}
repositories {
mavenLocal()
mavenCentral()
jcenter()
google()
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
maven { url "https://oss.sonatype.org/content/repositories/releases/" }
}
}
project(":desktop") {
apply plugin: "java-library"
dependencies {
implementation project(":core")
api "com.badlogicgames.gdx:gdx-backend-lwjgl:$gdxVersion"
api "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop"
api "com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-desktop"
api "com.badlogicgames.gdx:gdx-tools:$gdxVersion"
api "com.badlogicgames.gdx:gdx-controllers-desktop:$gdxVersion"
api "com.badlogicgames.gdx:gdx-controllers-platform:$gdxVersion:natives-desktop"
}
}
project(":core") {
apply plugin: "java-library"
dependencies {
api "com.badlogicgames.gdx:gdx:$gdxVersion"
api "com.badlogicgames.gdx:gdx-box2d:$gdxVersion"
api "com.badlogicgames.gdx:gdx-controllers:$gdxVersion"
api "net.dermetfan.libgdx-utils:libgdx-utils:0.13.4"
api "net.dermetfan.libgdx-utils:libgdx-utils-box2d:0.13.4"
}
}
If someone could help me out it would much appreciated. This is my first project in libGDX and I'm very stuck here, and I'm all out of ideas on how to find any clues to what might be wrong.
I just had the same issue and removing the ".atlas" from the filename fixed it. Although that is the file type, when I open my atlas file's properties in Windows explorer, the file type is simply listed as "file" rather than atlas.

Versioning Gradle native plugin builds

Here's my first attempt at a C program built with Gradle's C plugin:
apply plugin: 'c'
model {
components {
derpus(NativeExecutableSpec) {
sources {
c(CSourceSet) {
source {
srcDir "src/derpus/c"
include "**/*.c"
}
exportedHeaders {
srcDir "src/derpus/headers"
}
}
}
}
}
}
This produces an executable called derpus.exe. I would like, if at all possible, to version these executables (derpus-1.0.0.exe, derpus-1.0.1.exe, etc.). When I change the derpus closure to derpus-1.0.0 like so:
derpus-1.0.0(NativeExecutableSpec) {
And run gradle clean build I get:
D:\workspace\derp\20150505\derpus>gradlew clean build
FAILURE: Build failed with an exception.
* Where:
Build file 'D:\derpus\build.gradle' line: 6
* What went wrong:
Could not compile build file 'D:\derpus\build.gradle'.
> startup failed:
build file 'D:\derpus\build.gradle': 6: unexpected tok
en: 0 # line 6, column 20.
derpus-1.0.0(NativeExecutableSpec) {
^
1 error
Does anybody know of a way to version these executables?
Update
Now this is really weird! Taking Amnon's advice, I added a gradle.properties file that defined version=1.0.0. I then modified my model closure to:
model {
components {
derpus(NativeExecutableSpec) {
sources {
c(CSourceSet) {
source {
srcDir "src/derpus/c"
include "**/*.c"
}
exportedHeaders {
srcDir "src/derpus/headers"
}
}
}
baseName = "derpus-${version}"
}
}
}
This produces an executable named derpus-1 (what?!?!)!
So then I modified model again:
version = "3.4"
model {
components {
derpus(NativeExecutableSpec) {
sources {
c(CSourceSet) {
source {
srcDir "src/derpus/c"
include "**/*.c"
}
exportedHeaders {
srcDir "src/derpus/headers"
}
}
}
baseName = "derpus-${version}"
}
}
}
As you can see, this should overrdide the version set in gradle.properties, however after running gradle clean build, it produces derpus-3!
So I modified model yet again:
model {
components {
derpus(NativeExecutableSpec) {
sources {
c(CSourceSet) {
source {
srcDir "src/derpus/c"
include "**/*.c"
}
exportedHeaders {
srcDir "src/derpus/headers"
}
}
}
baseName = "derpus-3.4.5"
}
}
}
This produces derpus-3.4!!! What is going on here?!? Does the C plugin have a bug in it that doesn't honor the full version variable?
In your example above the problem with derpus-1.0.0 is the gradle things that the dash character is a minus which is unexpected in a component spec name, thus the failure. You can overcome this by wrapping derpus-1.0.0 with inverted commas. A better approach, however, would be to apply the version to the baseName property of the component spec, i.e. add the following line under derpus component definition:
baseName = "derpus-1.0.0"
or
baseName = "derpus-$version"
Where in the second case the version property $version is taken from the project object.
Update
Per smeeb comments below another workaround that can be applied is to directly rename the target binaries:
afterEvaluate {
RenameNativeBinaries()
}
def RenameNativeBinaries() {
binaries.all { b ->
if (b instanceof SharedLibraryBinarySpec) {
b.sharedLibraryFile = ReconstructFileName(b.sharedLibraryFile)
} else if (b instanceof StaticLibraryBinarySpec) {
b.staticLibraryFile = ReconstructFileName(b.staticLibraryFile)
}
}
}
def ReconstructFileName(File originalFile) {
def originalFileName = originalFile.absolutePath
def filePath = FilenameUtils.getFullPath(originalFileName)
def baseName = FilenameUtils.getBaseName(originalFileName)
def extension = FilenameUtils.getExtension(originalFileName)
def newName = "$baseName-$version.$extension"
def newFile = new File(filePath, newName)
newFile
}
Where FilenameUtils is taken from commons-io:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath group: 'commons-io', name: 'commons-io', version: '2.4'
}
}

Permanently add a plugin to Gradle

I use a third-party Gradle plugin in a lot of projects and would like to add this plugin permanently to my gradle installation. Currently I need to add the plugin to each build.gradle like so:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath "com.github.dcendents:android-maven-plugin:1.2"
}
}
Is there a way to add this plugin to my Gradle installation so that I don't need to include it in every build file?
I do realise it might not be the best practice and can result in unreproducible builds.
This is a hack and not a solution
Here is now an updated version which is also able to apply plugins and add maven repositories. Testet with gradle 2.10.
Add this Plugin to your .gradle/init.gradle:
apply plugin:AddDepPlugin
class AddDepPlugin implements Plugin<Gradle> {
def addDeps = [
"org.ensime.gradle": "gradle.plugin.net.coacoas.gradle:ensime-gradle:0.2.2",
"com.github.dcendents.android-maven": "com.github.dcendents:android-maven-plugin:1.2"]
def addRepos = ["https://plugins.gradle.org/m2/"]
void apply(Gradle gradle) {
def add = 0
gradle.allprojects { project ->
plugins.whenPluginAdded { t ->
if (++add == 1) {
project.getBuildScriptSource()
def bs = project.getBuildscript()
bs.getDependencies()
def repo = bs.getRepositories()
def ccf = bs.class.getDeclaredField("classpathConfiguration")
ccf.setAccessible(true)
def cc = ccf.get(bs)
addDeps.each { k,v-> cc.dependencies.add(project.dependencies.create(v))}
addRepos.each { k-> repo.maven { -> setUrl(k) } }
}
if (add == 8)
addDeps.each { k,v ->
if (!k.startsWith("x")) project.apply([plugin: k])
}
}
}
}
}
On http://ensime.github.io//build_tools/gradle/ I found this alternative solution (this is for the ENSIME plugin):
apply plugin: AddEnsimePlugin
class AddEnsimePlugin implements Plugin<Gradle> {
def supportedPlugins = [
'org.gradle.api.plugins.JavaPlugin',
'org.gradle.api.plugins.ScalaPlugin',
'jp.leafytree.gradle.AndroidScalaPlugin'
]
void apply(Gradle gradle) {
def added = false
gradle.allprojects { project ->
project.with {
if (parent == null) {
buildscript {
repositories {
jcenter()
maven {
name 'JFrog OSS Snapshot Repository'
url 'http://oss.jfrog.org/oss-snapshot-local'
}
}
dependencies {
classpath 'net.coacoas.gradle:ensime-gradle:0.2.6'
}
}
}
plugins.whenPluginAdded { plugin ->
if (!added && supportedPlugins.contains(plugin.class.name)) {
rootProject.apply plugin: 'org.ensime.gradle'
added = true
}
}
}
}
}
}
It works for me with Gradle 2.12. The other answer also works for me.

Categories

Resources