Do gradle configurations merge or override? - gradle

Say I define a plugin, like so:
import org.gradle.api.artifacts.dsl.RepositoryHandler
import org.gradle.api.artifacts.repositories.MavenArtifactRepository
import org.gradle.api.Project
import org.gradle.api.Plugin
class MyRepos implements Plugin<Project> {
static final String NEXUS_URL = 'http://nexus.mine.com/nexus/content/repositories/'
static final List<String> NEXUS_REPOS = [
'central',
'build',
'snapshots',
'release-candidates',
'releases',
]
void apply(Project project) {
project.repositories {
NEXUS_REPOS.each {
maven {
url (NEXUS_URL + it)
}
}
mavenLocal()
}
project.buildscript {
repositories {
maven {
url (NEXUS_URL + 'central')
}
mavenLocal()
}
}
}
}
and in a local build.gradle, I write
apply plugin: MyRepos
buildscript {
dependencies {
...
}
}
My desire is for the two buildscript sections to be merged such that the repositories are defined in the plugin and the dependencies in build.gradle, but it appears that the local declaration overrides the plugin and I end up with an error indicating "no repositories defined".
If I do this via configuration injection from the top level build.gradle, is the result the same?
Maybe the right solution is for the plugin to provide an ext closure to define useMyRepos() similar to the way mavenCentral() is used...

Generally configuration items in gradle are merged so you can apply configurations in different locations. You can, for example, configure some of the dependencies in one build script that will be applied to another build script that will add additional dependencies.
However, your case is a bit different since you're using buildScript configuration which is can be used to define the dependencies for the build script itself rather than the root repositories node which is intended for defining the dependencies of the project you build.
In this case, according to Purpose of buildScript in Gradle as these are different configurations you'll have to define your dependency twice.

Related

dependencies added in subprojects.forEach in gradle multi-module kotlin DSL is not visible to sub projects

I have multi-module gradle project with kotlin dsl called stream-data-processing. It is in github here.
The build.gradle.kts file of root project is -
plugins {
base
java
}
allprojects {
group = "streams-data-processing"
version = "1.0"
repositories {
jcenter()
mavenCentral()
mavenLocal()
}
dependencies {
subprojects.forEach {
compile("org.apache.kafka:kafka-streams:2.2.0")
testImplementation("junit:junit:4.12")
}
}
}
settings.gradle.kts is -
rootProject.name = "stream-data-processing"
include ("word-count-demo")
I have some sub-project called word-count-demo.
The build.gradle.kts file for this sub project is -
plugins {
java
application
}
But the classes in kafka-streams are not available in word-count-demo.
when I did `gradle word-count-demo:dependencies, it doesn't show the kafka dependencies available to the sub project.
I don't want to explicitly specify the dependencies in every project.
What is the mistake that went wrong here?
It appears this would be adding the same dependencies multiple times. I think you need to flip it around and call dependencies inside subprojects, and outside of allprojects, like so:
allprojects {
group ...
version ...
repositories ...
}
subprojects {
dependencies {
compile("org.apache.kafka:kafka-streams:2.2.0")
testImplementation("junit:junit:4.12")
}
}

Can not declare JSONObject type even added maven repository for it in the gradle with Intellij

I added https://mvnrepository.com/artifact/org.json/json into my gradle config like following:
allprojects {
...
repositories {
maven { url = 'https://mvnrepository.com/artifact/org.json/json'}
...
}
}
release ref link: https://mvnrepository.com/artifact/org.json/json/20180813
however, I wasn't able to import json by type in import org.json or import javax.json...
Anyone know why I can't import it? Because I am trying to use this type call JSONObject
Thanks
You should rather (unless you need to use JSONObject in build.gradle itself):
allprojects {
repositories {
mavenCentral()
}
dependencies {
compile group: 'org.json', name: 'json', version: '20180813'
}
}
You've just added a repository(?). You haven't explicitly requested anything from it yet.
Instead of doing it like that, Gradle comes with mavenCentral as a default repository. So all you need to do to get a dependency from it is declare it in your dependencies block.
apply plugin: 'java-library'
dependencies {
implementation 'org.json:json:20180813'
}

Gradle: Use BuildScript RepositoryHandler as Project Repository Handler

I'm implementing a custom plugin and inside this plugin I am providing a default repository configuration like so:
class MyPlugin implements Plugin<Project> {
...
...
...
#Override
void apply(Project project) {
project.repositories {
mavenLocal()
mavenCentral()
jcenter()
}
...
...
...
}
}
However, in order to be able to apply my plugin inside a build script, the client code will have a add a section like this in their build script anyway:
buildscript {
repositories {
mavenLocal()
maven { url "<organization maven repo url>" }
mavenCentral()
}
dependencies {
classpath 'com.organization.xxx:my-plugin:1.0.130'
}
}
apply plugin: 'com.organization.my-plugin'
Given, that, I'd like to be able to do something like this:
class MyPlugin implements Plugin<Project> {
...
...
...
#Override
void apply(Project project) {
project.repositories = project.buildscript.repositories
...
...
...
}
}
But, when I do that, I get an error, understandably, as the project.repositories property is read-only.
So, is there a proper way I could achieve what I want?
I think the error is because you are trying to assign a value to the property project.repositories. Fortunately, you just need to add repositories, so maybe this will work (untested)
#Override
void apply(Project project) {
project.repositories.addAll(project.buildscript.repositories)
}
By the way, I'm not sure you really want to do this. Better would be to define common repositories somewhere else and then maybe add to both buildscript and project

How to I preset a repository section in a gradle plugin?

I would like to define a plugin which sets the repositories{...} section in a gradle project to use our approved proxies and repos, and removes the need to define them in every project. How do I do that?
You can do it e.g. in the following way:
apply plugin: 'java'
apply plugin: Lol
dependencies {
compile 'com.google.guava:guava:18.0'
}
task cl(type: Copy) {
from configurations.compile
into 'libs'
}
class Lol implements Plugin<Project> {
void apply(Project p) {
def repositoriesConf = {
mavenCentral()
jcenter()
}
p.repositories(repositoriesConf)
}
}
There're really many different ways of implementing this task. Pay attention to the fact that also java plugin will be needed and maybe the plugin you need to implement should apply java plugin as well.

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);
// ...
}
// ...
}

Resources