Gradle 2.12 - Injecting plugins into sub-projects fails - gradle

I have a standard Gradle setup with a root and sub-projects. In my root build.gradle, I would like to configure a plugin and inject it into some of the sub-projects, e.g:
project(':web-app'){
apply plugin: 'gwt'
buildscript {
repositories {
jcenter()
maven { url 'http://dl.bintray.com/steffenschaefer/maven'}
}
dependencies {
classpath 'de.richsource.gradle.plugins:gwt-gradle-plugin:0.6'
}
}
gwt {
//Shared stuff goes in here ...
}
}
Unfortunately, I am getting:
A problem occurred evaluating root project 'XXXX'. Plugin with id
'gwt' not found.
What am I doing wrong? If I do the same in the sub-project(s) build.gradle, it works.
Bonus questions, if the above works at all:
How do I inject in several sub-projetcs? Seems like project(':a',':b'){...} does not work.
If the sub-project also has gwt{...} block, will it be merged with the stuff injected from the root? If so what takes precedence?
Thanks

Related

Cannot add subproject to gradle buildscript classpath in 7.3

I have a subprojectA and subprojectB. There are some artifacts from subprojectA that i need to build subprojectB. It seems that after upgrading to 7.3, i can no longer configure it like this.
Getting the error 'Cannot transition to state Configure as already transitioning to this state.'
May I know if there is an alternative or a solution to the error?
subprojectb build.gradle:
buildscript {
dependencies {
classpath project(':subprojectA')
}
}
plugins {
...
}
...
The solution is to make subprojectA an included build instead of a subproject, then use the GAV coordinates instead of the project dir.
//build.gradle
buildscript {
dependencies {
classpath 'com.example:subprojectA:1.0'
}
}
plugins {
...
}
...
// settings.gradle
includeBuild('./subprojectA')
https://docs.gradle.org/current/userguide/structuring_software_products.html#connecting_components

Gradle share properties in multi-project

I'm quite new to Gradle, trying to make multi-project. In root project declares all common libs (also their versions as properties) and apply plugins.
For example, root and child common projects.
In root's settings.gradle type:
rootProject.name = 'root'
include 'common'
In root's build.gradle type:
buildscript {
ext.kotlin_version = '1.3.11'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
subprojects {
buildscript {
repositories {
mavenCentral()
}
}
apply plugin: 'kotlin'
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}
}
And now I'd like to use another library only in specific child project. Do this in common's build.gradle:
buildscript {
dependencies {
classpath "org.jetbrains.kotlin:kotlin-allopen:$kotlin_version"
}
}
It's work fine when running gradle commands from root's folder, but failed with message Could not get unknown property 'kotlin_version' for object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler when running from common's folder.
What I'm doing wrong? Or is there any way around? And what are best practices for sharing libs and properties in multi-project?
For me, it looks like common know nothing about it's "parent" project, all relations defined in root's settings.
The reason why Gradle cannot resolve the property is because the project in folder common is named commons. This is caused by a spelling mistake in common's settings.gradle. This is fortunately easy to fix (common/settings.gradle) :
rootProject.name = 'common'
Alternatively, just delete the common/settings.gradle, it's fully optional in this case.
Consider reading the official Gradle documentation for authoring multi-project builds and the guide create multi-project builds for more information and best practices around multi-project builds.

Gradle buildSrc and buildscript

We have a Gradle build that includes a buildSrc with some custom plugins. Those plugins apply yet other plugins. For example, our plugin applies com.android.tools.build:gradle. For annotation processing that library needs to be on Gradle's classpath during compilation. So, putting this in our main build.gradle works:
buildscript {
repositories {
google()
}
dependencies {
classpath "com.android.tools.build:gradle:$gToolsVersion"
}
}
However, that means that for a user to apply this plugin they must (1) apply our plugin and (2) add that buildscript boilerplate. It seems like that shouldn't be necessary. We can also add a project.buildscript block inside our plugin but that too seems unnecessary and, due to this bug is problematic: https://developer.android.com/studio/build/gradle-plugin-3-0-0.html?utm_source=android-studio#known_issues.
I added the com.android.tools.build:gradle dependency to buildSrc/build.gradle as a runtime dependency. It seems like that should work: I thought that tells Gradle that in order to run my plugin that library (and its dependencies) need to be on the classpath. However, gradle buildEnvironment (and the fact that our build fails) makes it clear that's not the case.
So, questions:
What's the difference between a runtime dependency specified in buildSrc/build.gradle and a classpath dependency specified in a buildscript block in a regular build.gradle?
How can I arrange things so that users can apply the plugin from buildSrc and not have to also add the buildscript block to their build.gradle?
I got a slightly different problem and found an acceptable solution that might help with for your second question: I wanted to apply the same repositories in the buildSrc/build.gradle and twice in the root build.gradle.
repositories.gradle in the project root:
repositories {
if (project.hasProperty('nexus')) {
maven {
url 'http://localhost:8081/repository/JCenter/'
}
maven {
url 'http://localhost:8081/repository/Maven_Google/'
}
} else {
jcenter()
google()
}
}
ext {
androidGradleBuildToolsDependency = 'com.android.tools.build:gradle:3.1.3'
}
buildSrc/build.gradle:
buildscript {
apply from: '../repositories.gradle'
}
allprojects {
apply from: '../repositories.gradle'
}
dependencies {
// androidGradleBuildToolsDependency is defined in repositories.gradle
implementation androidGradleBuildToolsDependency
}
Root build.gradle:
buildscript {
apply from: 'repositories.gradle'
}
allprojects {
// this line will also be executed from the build.gradles in subprojects, so the working
// directory isn't always the same, so we use the absolute path here
apply from: "${rootProject.projectDir}/repositories.gradle"
}
Note that you do not need the classpath dependency inside the buildscript block of the root build.gradle as you normally would. The implementation dependency in the repositories.gradle seems to auto apply it.
My solution probably doesn't work when the build.gradles are supplied via a dependency.
Stumbled upon this while digging into a tangential problem.
I've been successfully using buildSrc/build.gradle as the place to define dependencies that would normally belong in the root-project's buildscript classpath for a few of my projects.
You can see a working example here: https://github.com/episode6/chop/blob/develop/buildSrc/build.gradle
I used to use compile dependencie but just switched to runtimeClasspath which feels more appropriate and also works. I don't think your classpath dependencies were working because they would be on the classpath of the buildSrc project, but not compiled into or run along side it.
If you decide to go this route, you may run into the problem I was just digging into which only came up because of this approach.
When I tried this approach with the dokka plugin, I got the following error
Could not resolve all files for configuration ':detachedConfiguration1'.
> Cannot resolve external dependency org.jetbrains.dokka:dokka-fatjar:0.9.17 because no repositories are defined
I was able to workaround this by adding jcenter() to the root project's buildscript repositories: https://github.com/episode6/chop/blob/develop/build.gradle#L2

Gradle's com.moowork.gradle.grunt plugin

I have a webapp compilation subproject which is written in a separate script plugin and is being added to the root project via "apply from: scriptSrc" syntax. Top of my script plugin looks like this:
buildscript {
repositories {
jcenter()
}
dependencies{
classpath 'com.moowork.gradle:gradle-grunt-plugin:0.10'
}
}
apply plugin: "com.moowork.grunt"
However its not recognizing the plugin and fails on the initialization phase saying
Plugin with id 'com.moowork.grunt' not found.
I am following this: https://plugins.gradle.org/plugin/com.moowork.grunt/0.10.
Anyone else having issues with grunt plugin inclusion in script plugin?
Not sure exactly what exactly is causing the issue. Make sure you have the buildscript setup the following way.
apply plugin: 'com.moowork.grunt'
buildscript{
dependencies{
classpath 'com.moowork.gradle:gradle-grunt-plugin:0.13'
classpath 'com.moowork.gradle:gradle-node-plugin:0.12'
}
// In this section you declare where to find the dependencies of your project
repositories {
jcenter()
mavenCentral()
}
}
If you go plan to use plugin:0.13, you need to include the node-plugin as well or else you may get a NoClassDefFound Exception. This may not be necessary if you continue to use version 0.10.
Also, if you are working on a gradle project in eclipse and building the project from commandline, make sure you refresh the project so build reflects in your workspace.

Gradle: Inject plugins to subprojects

I came across gradle plugin to help me to deal with dotted property names. It works fine in single project when used like this:
apply plugin: 'config'
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.esyfur:gradle-config-plugin:0.4.+'
}
}
task printProps() {
println(config.grafana.url)
}
However, I want to use this plugin in multiple projects (multi-module) and would like idealy not to repeat such initialization in every project but rather inject it somehow to have it more manageable.
I have failed to find out how to do it or if it can be done. I tried e.g. in parent build.gradle use this:
allprojects {
apply plugin: 'config'
}
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.esyfur:gradle-config-plugin:0.4.+'
}
}
but it does not work. Gradle complains that it can not find property 'config' on task.
Update
After Peter's comment I started wondering around and creating an example project from the scratch and incrementally get it closer to my 'real project'. I was not completely precise in describing my setup. In settings.gradle I use
rootProject.children.each { project ->
project.buildFileName = "${project.name}.gradle"
}
which causes this problem. Everything works fine When switched back to build.gradle names.
The problem is that your settings.gradle doesn't configure rootProject.buildFileName to match the non-standard filename used for the build script. Therefore the build script doesn't get evaluated, and its buildscript block never takes effect.

Resources