How to load Gradle Plugin (with its depenecies) into build.gradle? - gradle

I have a project that has two gradle files: build.gradle and myPlugin.gradle
The myPlugin.gradle implemented the Plugin Interface. The plugin also has a dependency on osdetector-gradle-plugin
I added the two gradle files beside each other then I tried to apply myPlugin into build.gradle as follows:
apply from: 'myPlugin.gradle'
However, I have got the following error in myPlugin.gradle file:
Plugin with id 'com.google.osdetector' not found
Here is the code for myPlugin.gradle file:
apply plugin: 'groovy'
apply plugin: 'maven'
repositories {
mavenCentral()
mavenLocal()
}
dependencies {
compile 'com.google.gradle:osdetector-gradle-plugin:1.4.0'
}
import org.gradle.api.tasks.TaskAction
import org.gradle.api.DefaultTask
import org.gradle.api.Plugin
import org.gradle.api.Project
apply plugin: 'com.google.osdetector'
apply plugin: HostingMachineOSPlugin
class HostingMachineOSPlugin implements Plugin<Project>{
void apply(Project project){
project.plugins.apply("com.google.osdetector");
//project.configurations.files('com.google.osdetector')
println project.osdetector.os
/* Extend the project property to have the class HostingMachineOS */
project.ext.HostingMachineOS = HostingMachineOS
}
}
public class HostingMachineOS {
static family = "Unkown"
static def setFamilyName(name){
family = name
}
static def isLinux (){
family == "linux"
}
static def isWindows (){
family == "windows"
}
static def isMacOS(){
family == "osx"
}
}
HostingMachineOS.setFamilyName(osdetector.os)
in build.gradle file: I am just doing something like this:
//define buildScript repositories and dependencies then
apply from: 'myPlugin.gradle'
task dummy{
println HostingMachineOS.isMacOS()
println HostingMachineOS.isLinux()
println HostingMachineOS.isWindows()
}
How can I solve the Plugin with id 'com.google.osdetector' not found?

This is a common pitfall, to add a plugin to build.gradle file you need to add a dependency for the build script itself - not for the project. The following piece of code (added in the file where you apply the plugin) should solve the problem:
buildscript {
repositories {
mavenCentral()
mavenLocal()
}
dependencies {
classpath 'com.google.gradle:osdetector-gradle-plugin:1.4.0'
}
}
EDIT
Please have a look here - it seems that if you need to apply from third-party script you need to use the full class name (with package). So the files should be defined as follows:
build.gradle
apply from: 'myPlugin.gradle'
task dummy{
println HostingMachineOS.isMacOS()
println HostingMachineOS.isLinux()
println HostingMachineOS.isWindows()
}
myPlugin.gradle
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.google.gradle:osdetector-gradle-plugin:1.4.0'
}
}
apply plugin: 'groovy'
apply plugin: 'maven'
apply plugin: com.google.gradle.osdetector.OsDetectorPlugin
apply plugin: HostingMachineOSPlugin
class HostingMachineOSPlugin implements Plugin<Project>{
void apply(Project project){
project.plugins.apply(com.google.gradle.osdetector.OsDetectorPlugin);
//project.configurations.files('com.google.osdetector')
println project.osdetector.os
/* Extend the project property to have the class HostingMachineOS */
project.ext.HostingMachineOS = HostingMachineOS
}
}
public class HostingMachineOS {
static family = "Unkown"
static def setFamilyName(name){
family = name
}
static def isLinux (){
family == "linux"
}
static def isWindows (){
family == "windows"
}
static def isMacOS(){
family == "osx"
}
}
HostingMachineOS.setFamilyName(osdetector.os)

Related

how to use a plugin inside a groovy plugin

I am trying to migrate tasks from build.gradle to a plugin that do it.
In my build.gradle I do this:
plugins {
//id 'java'
id 'war'
//https://plugins.gradle.org/plugin/org.gretty
id 'org.gretty' version '3.0.1'
id "com.github.dkorotych.gradle-maven-exec" version "2.2.1"
}
apply plugin: 'maven'
....
....
prepareFrontEnd (type: MavenExec, dependsOn: build) {
goals 'vaadin:prepare-frontend'
}
task buildFrontEnd (type: MavenExec, dependsOn: prepareFrontEnd) {
goals 'vaadin:build-frontend'
}
Now I am moving this stuff to a plugins:
package com.github.mdre.hgvaadinplugin
import org.gradle.api.Plugin;
import org.gradle.api.Project;
//import com.github.dkorotych.gradle.maven.exec.MavenExec;
class HGVaadinPlugin implements Plugin<Project> {
#Override
void apply(Project project) {
println "Hybrid Gradle Vaaadin plugin."
project.plugins.apply('com.github.dkorotych.gradle-maven-exec')
// project.getPluginManager().apply('gradle-maven-exec-plugin')
project.task('prepareFrontEnd', type: MavenExec){
dependsOn build
doLast {
goal 'vaadin:prepare-frontend'
}
}
}
}
If I try to import the class MavenExec I get this error:
> Task :compileGroovy FAILED
startup failed:
/home/mdre/Proyectos/HGVaadinPlugin/src/main/groovy/com/github/mdre/hgvaadinplugin/HGVaadinPlugin.groovy: 5: unable to resolve class com.github.dkorotych.gradle.maven.exec.MavenExec
# line 5, column 1.
import com.github.dkorotych.gradle.maven.exec.MavenExec;
^
and if I comment the import line, I get this error in the project that use the plugin:
What went wrong:
A problem occurred evaluating root project 'VaadinFlowLab'.
Failed to apply plugin [id 'com.github.mdre.hgvaadinplugin']
No such property: MavenExec for class: com.github.mdre.hgvaadinplugin.HGVaadinPlugin
How could I do this?
Thanks.
Well, I fix it!
I forget to include the dependency class in the final jar. So all of I need was to add this to the build.config:
configurations {
// configuration that holds jars to include in the jar
extraLibs
}
dependencies {
....
....
//necesario para crear un fatJar
extraLibs "gradle.plugin.com.github.dkorotych.gradle.maven.exec:gradle-maven-exec-plugin:2.2.1"
configurations.compile.extendsFrom(configurations.extraLibs)
}
jar {
from {
configurations.extraLibs.collect { it.isDirectory() ? it : zipTree(it) }
}
}
and now it is working!!

how to proguard with spring-boot gradle plugin

How to setup proguard obfuscation with spring boot 2 and gradle build?
Hello. Trying to setup code obfuscation of Spring Boot app with its gradle plugin and Proguard gradle plugin. Google mostly gives some approaches for older spring-boot-gradle-plugin version (i.e. this closest one using non-existing bootRepackage task), or using maven plugin (having repackage goal).
Idea is to obfuscate classes before jar packaging, as I understand, but I don't see any entry points in current gradle plugin version, and would like to avoid manual extraction and zipping back.
Is anyone using that combo at all? Spring Boot version >=2.0.3.
I think that today is not possible and you have to do it with manual extraction and zipping back.
An example of manual extraction and zipping back which could be helpful:
build.gradle
version = '0.1.0'
buildscript {
dependencies {
classpath 'net.sf.proguard:proguard-gradle:6.0.3'
classpath 'net.sf.proguard:proguard-base:6.0.3'
}
}
apply plugin: 'java'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
task extractJar(type: Copy) {
def zipFile = file("${buildDir}/libs/your_project_name-${version}.jar")
def outputDir = file("${buildDir}/unpacked/")
from zipTree(zipFile)
into outputDir
}
task proguard(type: proguard.gradle.ProGuardTask) {
doFirst {
tasks.extractJar.execute();
}
configuration 'proguard.conf'
injars "${buildDir}/unpacked/BOOT-INF/classes"
outjars "${buildDir}/obfClasses"
libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
libraryjars "${buildDir}/unpacked/BOOT-INF/lib"
doLast {
tasks.deleteClasses.execute();
}
}
task deleteClasses(type: Delete) {
delete "${buildDir}/unpacked/BOOT-INF/classes/"
doLast {
tasks.copyObfuscatedClasses.execute()
}
}
task copyObfuscatedClasses(type: Copy) {
from "${buildDir}/obfClasses"
into "${buildDir}/unpacked/BOOT-INF/classes/"
include 'com/**'
include '*.properties'
doLast {
tasks.copyObfuscatedJars.execute()
}
}
task copyObfuscatedJars(type: Copy) {
from "${buildDir}/obfClasses"
into "${buildDir}/unpacked/BOOT-INF/lib/"
include '*.jar'
doLast {
tasks.deleteObfuscated.execute()
}
}
task deleteObfuscated(type: Delete) {
delete 'build/obfClasses'
doLast {
tasks.repackage.execute()
}
}
task repackage(type: Zip) {
from "${buildDir}/unpacked"
entryCompression ZipEntryCompression.STORED
archiveName "your_project_name-${version}-obf.jar"
destinationDir(file("${buildDir}/libs"))
}
proguard.conf
-ignorewarnings
-keepdirectories
-keep interface com.your_package.** { *; }
-keep class com.your_package.main{ *; }
-keep class com.your_package.model.** { *; }
-keepparameternames
-keepclassmembers #org.springframework.** class * {
*;
}
-keepclassmembers #org.springframework.** interface * {
*;
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep #org.springframework.** class *
-keepclassmembers #javax.** class * { *; }
-dontwarn org.springframework.**
-dontwarn javax.**
-dontwarn org.yaml.snakeyaml.**
-dontwarn okhttp3.**
have you tried writing a task for it in your build.gradle?
task obfuscate(type: proguard.gradle.ProGuardTask, dependsOn: jar) {
mustRunAfter ('javadoc')
inputs.file file("${jar.archivePath}")
outputs.file file("$buildDir/proguard/${project.name}-${project.version}.jar")
injars "${jar.archivePath}"
// JDK 8 and below use jars on the classpath
if (JavaVersion.current().java8Compatible && !JavaVersion.current().java9Compatible) {
println "Obfuscation inputs based on JDK 8 layout."
libraryjars "$javaHome/lib/rt.jar"
libraryjars "$javaHome/lib/jce.jar"
libraryjars "$javaHome/lib/ext/jfxrt.jar"
} else {
// JDK 9 and above use modules on the module-path
println "Obfuscation inputs based on JDK 9+ module layout."
def jdkModuleList = [
'java.base', 'java.datatransfer', 'java.desktop',
'java.instrument', 'java.logging',
'java.management', 'java.prefs', 'java.rmi',
'java.scripting', 'java.xml',
'jdk.attach'
]
jdkModuleList.forEach {
libraryjars "$javaHome/jmods/${it}.jmod", jarfilter: '!**.jar', filter: '!module-info.class'
}
target '10' // JDK 9 is obsolete, would target 11, but Proguard can't deal with 11's class files yet
}
// dependencies
configurations.runtime.files.each {
libraryjars it, filter: '!META-INF/versions/**'
}
outjars "$buildDir/proguard/${project.name}-${project.version}.jar"
printseeds "$buildDir/proguard/proguard_seeds.txt"
printmapping "$buildDir/proguard/proguard_map.txt"
configuration 'src/main/proguard/configuration.pro'
}
this thread might be helpful with your situation:
https://discuss.gradle.org/t/obfuscated-jars-what-are-the-best-practices/18834/6

gradle plugin dependencies not found under buildSrc

I have a working build.gradle that I'd like to refactor into the buildSrc directory but I'm having trouble finding the dependencies.
Working build.gradle:
import groovyx.net.http.HTTPBuilder
buildscript {
repositories {
mavenCentral()
jcenter()
}
dependencies {
classpath 'org.codehaus.groovy.modules.http-builder:http-builder:0.7.2'
}
}
plugins {
id 'groovy'
}
group "com.example"
version "0.0.1"
class Foo {
Foo() {
new HTTPBuilder('http://www.example.com')
}
}
Non-working refactored build.gradle:
However, when I try to split into the following:
build.gradle
buildscript {
repositories {
mavenCentral()
jcenter()
}
dependencies {
classpath 'org.codehaus.groovy.modules.http-builder:http-builder:0.7.2'
}
}
plugins {
id 'groovy'
}
group "com.example"
version "0.0.1"
and buildSrc/src/main/groovy/Foo.groovy
import groovyx.net.http.HTTPBuilder
class Foo {
Foo() {
new HTTPBuilder('http://www.example.com')
}
}
Gives the error:
C:\Project\buildSrc\src\main\groovy\Foo.groovy: 7: unable to resolve
class HTTPBuilder # line 5, column 26.
HTTPBuilder client = new HTTPBuilder('http://www.example.com')
How can I get gradle to recognise the dependencies?
You need to create a build.gradle file for buildSrc directory. Try this:
C:\Project\buildSrc\build.gradle
apply plugin: 'groovy'
repositories {
mavenCentral()
jcenter()
}
dependencies {
compile 'org.codehaus.groovy.modules.http-builder:http-builder:0.7.2'
}
There is more details in this documentation section.

How to apply a Gradle plugin from another plugin?

I'm trying to encapsulate android plugin in my own plugin, but when I'm trying to apply my plugin build fails with an exception:
A problem occurred evaluating root project 'myproj'.
> Failed to apply plugin [id 'com.mycomp.build']
> Failed to apply plugin [id 'android-library']
> Plugin with id 'android-library' not found.
Here is how I'm applying android plugin inside my own plugin's implementation:
// build.gradle
apply plugin: 'groovy'
version = '1.0'
group = 'com.mycomp'
dependencies {
compile gradleApi()
compile localGroovy()
}
// Build.groovy
package com.mycomp
import org.gradle.api.Plugin
import org.gradle.api.Project
class Build implements Plugin<Project> {
void apply(Project project) {
println 'Hello from com.mycomp.Build'
project.beforeEvaluate {
buildscript.configurations.classpath +=
'com.android.tools.build:gradle:1.0.0-rc1'
}
project.configure(project) {
buildscript.repositories.mavenCentral()
apply plugin: 'android-library'
}
}
}
For some reason a classpath is not being properly loaded, what am I doing wrong?
I guess that at the time you'd like to add the plugin dependencies for the build script have been already resolved, thus it won't work that way. You need to specify the plugin You'd like to apply as a script dependency itself.
It will work that way:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.0.0-rc1'
}
}
apply plugin: 'groovy'
apply plugin: Build
version = '1.0'
group = 'com.mycomp'
dependencies {
compile gradleApi()
compile localGroovy()
}
import org.gradle.api.Plugin
import org.gradle.api.Project
class Build implements Plugin<Project> {
void apply(Project project) {
project.configure(project) {
apply plugin: 'android-library'
}
}
}
Now, android-plugin is found but it fails because of the fact that groovy plugin had been applied earlier and there's a conflict.
Use the project's PluginManager. For example, the war plugin pulls in the java plugin like this:
public class WarPlugin implements Plugin<Project> {
// ...
public void apply(final Project project) {
project.getPluginManager().apply(org.gradle.api.plugins.JavaPlugin.class);
// ...
}
// ...
}

Why gradle's buildscript classpath doesn't contain buildSrc?

i can't see buildSrc on the buildscript classpath in gradle; i can access it...but it somehow isn't there
i expected that it's there...because the buildscript can use those classes
build.gradle:
apply plugin: 'java'
buildscript{
dependencies{
classpath gradleApi()
}
}
task show(){
A.asd()
buildscript.configurations.classpath.each { println it }
}
contents of: buildSrc/src/main/java/A.java
public class A{
public static void asd(){
System.out.println(A.class + " is invokable from"+A.class.getProtectionDomain().getCodeSource().getLocation().getPath());
}
}
output:
:buildSrc:clean
...
:buildSrc:build
class A is invokable from/home/kirk/projects/bt/ews/tx3/buildSrc/build/classes/main/
/home/kirk/tools/gradle-1.11/lib/gradle-core-1.11.jar
...other nonrelated jars/etc
:show
buildscript { dependencies { classpath ... } } is the way to explicitly add build script dependencies. The buildSrc output directory is added implicitly.

Resources