specify classpath for plugin inside apply method - gradle

How to specify classpath for custom gradle plugin inside class, that implements interface Plugin?
class TaskPlugin implements Plugin<Project> {
void apply(Project project) {
project.task('task') << {
println 'simple task'
}
}
}
I saw something similar there
https://github.com/gradle/gradle/blob/6277a4dc70fbeea83c111e75c95ba851d1e56ffc/subprojects/plugins/src/main/groovy/org/gradle/api/plugins/WarPlugin.java#L25
However I don't know how to apply it for my case. Specifically I want to use both test and main sourcesets.
I want to get rid of classpath dependencies, related to my project. Because I have the same dependencies in dependencies and in buildscript { dependencies {
Every time I add plugin I have to add classpath dependencies, which that plugin is using.
apply plugin: 'my-plugin'
task {
... do something
}
buildscript {
repositories {
flatDirs dir('.')
}
dependencies {
classpath ("my-group:my-plugin:my-version")
classpath ("dependency:dependency:dependency")
}
}
The problem is that when I specify basic dependencies (not inside buildscript) I may have the same dependencies
dependencies {
compile ("dependency:dependency:dependency")
}
Sometimes I need some compiled project dependencies compile project(":my-project") which I have to specify using classpath files("path to compiled").
How to adjust plugin implementation to remove those dependency duplicates? Like for example if I declared dependency using compile or runtime - plugin will know about it and there is no need to declare dependency in classpath explicitly.

Related

Injecting plugin/runtimeOnly configuration(s) from one module to another module (within the same project) in gradle multi module project

I am referring to my post here :Moving Jib configuration of one module into a new module, to refactor multi-module gradle project
With the same refactoring goal of keeping jib related configuration in a separate module, I want to inject some "runtimeOnly" dependencies from the new module so that jar gets added in the classpath.
['jib', 'jibDockerBuild', 'jibBuildTar'].each { jibTaskName ->
task "${jibTaskName}Webapp" {
doFirst {
project(':webapp').jib {
to.image = 'jib-webapp'
// and more ....
}
***project(':webapp').configurations {
dependencies {
runtimeOnly project(':abc')
}
}***
}
finalizedBy ":webapp:$jibTaskName"
}
task "${jibTaskName}App" {
doFirst {
project(':app').jib {
to.image = 'jib-app'
// and more ...
}
}
finalizedBy ":app:$jibTaskName"
}
}
but ./gradlew jibDockerBuildWebapp won't add the ":abc" module artifacts (jar) in the war lib directory.
Only way I am able to get this working by adding "runtimeOnly project(':abc') in the ":webapp" module's build.gradle file.. but that's not I intend to do.
Can you please suggest how to get this working?
I was searching for diff options in Jib settings if I could add the module dependency there for it to add the artifacts in the lib directory. I need to add additional jars to run a setup program before starting tomcat.
You can just add dependencies to a module from another module.
// to make sure :webapp is evaluated before this project
evaluationDependsOn(':webapp')
project(':webapp').dependencies {
runtimeOnly 'junit:junit:4.13'
}
['jib', 'jibDockerBuild', 'jibBuildTar'].each { jibTaskName ->
...
However, I'm not sure if this is a good practice. It's the same as defining dependencies in the target build.gradle, and the only difference is that it's being done at a different place. I think this may confuse first-time readers of your repo as to how and why some dependencies are added out of the blue.
BTW, the following also worked for me:
...
task "${jibTaskName}Webapp" {
doFirst {
project(':sub1') {
jib.to.image='jib-sub1'
dependencies {
runtimeOnly 'junit:junit:4.13'
}
}
}
}
However, it's not exactly same as above in that the dependencies are added in a later phase (not in the Gradle configuration phase) and only when the task is executed. Again, I'm not sure if this is a good practice.

How to change name of java library when build with gradle?

I'm trying to build a java library for my other java projects. I'm also trying to learn gradle. There is a tutorial : https://docs.gradle.org/current/samples/sample_building_java_libraries.html shows how to build libraries with gradle.
But somehow when I use gradlew build it always gives me lib-< version >.jar and creates a folder called lib and I can't change it.
This is my settings.gradle
rootProject.name = 'myOwnLibrary'
include('lib')
this is my build.gradle (inside lib folder)
plugins {
// Apply the java-library plugin for API and implementation separation.
id 'java-library'
}
version = "0.1.1"
tasks.named('jar') {
manifest {
attributes('Implementation-Title': project.name,
'Implementation-Version': project.version)
}
}
repositories {
// Use JCenter for resolving dependencies.
jcenter()
}
dependencies {
// Use JUnit test framework.
testImplementation 'junit:junit:4.13'
// This dependency is exported to consumers, that is to say, found on their compile classpath.
api 'org.apache.commons:commons-math3:3.6.1'
// This dependency is used internally, and not exposed to consumers on their own compile classpath.
implementation 'com.google.guava:guava:29.0-jre'
}
With Kotlin DSL example, you can add in your tasks jar the following snippet:
tasks.jar {
manifest {
attributes(mapOf("Implementation-Title" to rootProject.name,
"Implementation-Version" to project.version))
}
archiveBaseName.set(rootProject.name)
}
where rootProject.name, is the value localized into settings.gradle.kts file.

build.gradle buildscript dependencies vs. dependencies?

Can someone explain to me how depedencies listed in the "buildscript" in the build.gradle file are different than regular dependencies listed in the dependencies block { } ? and why they have to be listed with the syntax "implementation"? I've googled this and responses say the dependencies in the buildscript and used to "build the project" but I don't understand this? can anyone give a more clear picture and answer?
buildscript:
buildscript
{
repositories
{
maven {
url 'myMavenFeed'
credentials {
username "myUsername"
password myPassword
}
}
mavenCentral()
jcenter()
}
dependencies
{
classpath "com.microsoft.azure.sdk.iot:iot-device-client:1.14.1"
}
}
Dependencies block:
dependencies
{
compile group: 'com.microsoft.azure.sdk.iot', name: 'iot-device-client', version: '1.16.0'
}
Can someone explain to me how depedencies listed in the "buildscript" in the build.gradle file are different than regular dependencies listed in the dependencies block { } ?
Dependencies defined in the buildscript { } block are dependencies to use to build your project. These dependencies are available to use in your Gradle build file (build.gradle or build.gradle.kts)
Dependencies defined in the dependencies { } are for your application code.
So for your samples in your questions, does it make sense for Gradle (the build system) to have iot-device-client on its classpath? Why does a build system need iot-device-client on its classpath to build your project? It doesn't make sense therefore it should be removed.
Now let's say you are developing an application the requires some functionality or class from iot-device-client. You need a way to add this library to your application's code/classpath. You when then declare it as a dependency as you have done above:
dependencies {
implementation("com.microsoft.azure.sdk.iot:iot-device-client:1.16.0")
}
References:
External dependencies for the build script
Declaring depenedncies
and why they have to be listed with the syntax "implementation"?
implementation is known as a configuration: A Configuration represents a group of artifacts and their dependencies
There are many more configurations depending on the plugins you apply to your project. For example, if you apply the Java plugin:
plugins {
id("java")
}
The following configurations are available to use:
implementation
compileOnly
compileClasspath
...and many more
Each one has their own meaning/usage and I strongly suggest reading about them here.

How to use init.gradle to provide plugin repositories for plugins configured in the settings.gradle

I have configured a Gradle plugin in settings.gradle file as follows,
buildscript {
dependencies {
classpath "org.test.group:gradleplugins:${pluginVersion}"
...
}
}
apply plugin: 'org.test.group:gradleplugins'
....
and I am trying to provide artifacts repository using init.gradle as follows,
initscript {
repositories {
maven { url "https://test.repo/gradleplugins" }
...
}
}
also, I have provided init.gradle file to the build task using,
.... -i -I ./init.gradle'
but the build still gets a dependency resolution error as follows,
Cannot resolve external dependency org.test.group:gradleplugins:1.0.0-SNAPSHOT because no repositories are defined.
It could be done either way by writing Gradle plugin in the init.gradle file as following,
apply plugin: EnterpriseRepositoryPlugin
class EnterpriseRepositoryPlugin implements Plugin<Gradle> {
void apply(Gradle gradle) {
gradle.settingsEvaluated { settings ->
settings.pluginManagement {
repositories {
maven { url "https://repo.org/gradleplugins" }
maven { url "https://repo.org/maven" }
}
}
}
}
}
according to Gradle documentation,
https://docs.gradle.org/current/userguide/init_scripts.html
The init.gradle has another purpose (and that file is being automatically detected).
void settingsEvaluated​(Settings settings) might be to only chance to manipulate these settings (but the question does not provide the least valid reason to do so, with only one repository). It rather seems that you're unnecessarily over-complicating things, where there otherwise would be no problem. And this doesn't belong into the settings.gradle either (which also has another purpose). Just add the plugin repositories into the buildscript block of the root project's build.gradle, where they belong. The userguide shows how it should look alike, when defining the plugin repositories statically.

How to add buildscript dependencies in custom plugin to project dependency?

I wrote a custom gradle plugin which comes with an additional compile step. For the compilation some classes of the plugin itself are needed, since it is an annotation processor.
I try to solve it by adding the plugin as a compile dependency this way:
// in the custom plugin
project.dependencies {
compile "com.thilko.spring:gradle-springdoc-plugin:0.1.SNAPSHOT"
compile localGroovy()
}
This solution is working but introduces duplication since I have to declare the same plugin version that is already declared in the build script section of the project that uses the plugin:
// build.gradle of the project that uses the plugin
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "com.thilko.spring:gradle-springdoc-plugin:0.1"
}
}
apply plugin: 'springdoc'
Is there a way to reuse the dependencies defined in the buildscript section?
If you think it's worth it, you can declare an extra property inside the buildscript block (e.g. ext.springdocPlugin = "com.thilko.spring:gradle-springdoc-plugin:0.1.SNAPSHOT"), and then reuse it from outside (e.g. dependencies { compile buildscript.springdocPlugin }).
If you add the dependency to the pom of the your plugin, it will be added to the buildscript dependencies of the project you apply your plugin to.

Resources