Why Does gradle eclipseClasspath task does not include transitive project dependencies? - gradle

I created a simple example(the names don't really mean anything):
folder structure:
gradleMultiProject
build.gradle
core
build.gradle
src
main
java
Core.java
database
build.gradle
src
main
java
Database.java
settings.gradle
webapp
build.gradle
src
main
java
Webapp.java
Below are the files mentioned above:
build.gradle (root gradle build file under gradleMultiProject folder)
subprojects {
apply plugin: 'java'
apply plugin: 'eclipse'
}
settings.gradle
include 'core', 'database', 'webapp'
gradleMultiProject\core\src\main\java\Core.java
package main.java;
public class Core
{
public static String HELLO_MESSAGE = "hello world!";
}
Core's build.gradle
task hello {
println "hello from core!"
}
gradleMultiProject\database\src\main\java\Database.java
package main.java;
public class Database
{
public void saveMessage()
{
System.out.println(Core.HELLO_MESSAGE);
}
}
Database's build.gradle
dependencies {
compile project(':core')
}
gradleMultiProject\webapp\src\main\java
package main.java;
public class Webapp
{
public static void main(String[] args)
{
Database database = new Database();
database.saveMessage();
System.out.println(Core.HELLO_MESSAGE);
}
}
Webapp's build.gradle
dependencies {
compile project(':database')
}
Gradle compiles everything just fine(gradle build). It even lists the transitive dependencies just fine(gradle dependencies). But when I try to generate a .classpath file(gradle eclipseClasspath) for the webapp project it doesn't include core. WHY?!?!?!?!?!

Actually this isn't a problem because eclipse "exports" core in database. What that means is that it will show up in any project that require the database project.
I just created this exact project and ran "gradle eclipse" and there are no build errors because the webapp project requires the database project and the database project requires and exports the core project. To see more look at the build path in eclipse.

Related

Task 'run' not found in root project

My "build.gradle" file:
apply plugin: 'java'
sourceSets {
main {
java {
srcDir 'src'
}
}
test {
java {
srcDir 'test'
}
}
}
My "Main.java" file in "./src/" directory:
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args) {
System.out.println("Hello Gradle");
}
}
I get this error:
Task 'run' not found in root project 'gradleNew'
Sorry for the stupid question... I didn't use Gradle before
The java plugin does not include the run task, which I suppose your gradle build requires somewhere in your app.
Change the java plugin to application and you should be fine.
To verify this, you can go to your project folder inside you terminal and run gradle tasks. You should see the run task listed among other tasks.
I hope that helps.
I just add this code and my app run:
plugins {
id 'application'
}
Try this instead:
group 'com.example'
version '1.0'
apply plugin: 'application' // implicitly includes the java plugin
sourceCompatibility = 1.11 // java version 11
repositories {
mavenCentral()
}
dependencies {
// your dependencies
}
sourceSets {
main {
java {
srcDirs = ['src/main/java']
}
resources {
srcDirs = ['src/main/resources']
}
}
}
I typically use something similar to this for my projects. You can then explicitly create the relevant dirs for src/test code, or sometimes the IDE will do it for you when you point it to the relevant build.gradle file (you can typically restart the IDE and it will pick up the file, or you can open a new project and select the build.gradle file as the project to open if it doesn't identify it right away).

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")
}
}

Avoiding Duplicate Repository Declaration in Multi Module Gradle Project

Lets say I have two projects in a multimodule gradle (4.2) repository with the following configurations:
Project A build.gradle:
dependencies {
compile (group: 'org.example', name: 'dependency-of-vast-importance', version: '17.2') {
}
repositories {
maven {
url "http://download.example.org
}
}
Project B build.gradle:
dependencies {
compile project(":projectA")
compile (group: 'org.anotherdependency', name: 'anotherdependency', version: '1.0')
}
repositories {
maven {
url "http://download.anotherdependency.org
}
}
With this configuration, Project B will fail to build -claiming in cannot find dependency-of-vast-importance.
So far, the only "solution" I have found for successfully completing the build requires writing the build.gradle for projectB like:
dependencies {
compile project(":projectA")
compile (group: 'org.anotherdependency', name: 'anotherdependency', version: '1.0')
}
repositories {
maven {
url "http://download.anotherdependency.org
}
maven {
url "http://download.example.org
}
}
This approach is worthless because it requires that I copy the repository declarations for ProjectA to all other projects that depend on it -which defeats the purpose of dependency management and modules.
How can I avoid specifying all the repositories necessary for Project A in Project B's build.gradle?
Use in root build.gradle:
allprojects {
repositories {
maven { url 'http://download.anotherdependency.org' }
maven { url 'http://download.example.org' }
}
}
This code will apply repositories to all projects

gradle common code for multiproject build

I have some common class definitions for a multiproject build in folder buildSrc:
root
build.gradle
settings.gradle
a/
build.gradle
b/
build.gradle
buildSrc/
common.gradle
where
settings.gradle says
include ':a', ':b'
a/build.gradle
project(":a") {
task someTask(type: CommonTask) {
println "Running some task"
}
}
buildSrc/common.gradle
class CommonTask extends DefaultTask {
#TaskAction
def someAction() {
println "Running common task"
}
}
According to docs:
https://docs.gradle.org/current/userguide/organizing_build_logic.html
buildSrc project. Drop the source for your build classes into a
certain directory and Gradle automatically compiles them and includes
them in the classpath of your build script.
However when running gradle build I get an error:
Could not find property 'CommonTask' on project ':a'.
So how can we have common class definitions for a multiproject build?
Edit
Adding apply from: "$rootDir/buildSrc/common.gradle" to project a does not help
Edit2
I put the file common.gradle to buildSrc/src/main/groovy/org/gradle/Common.groovy
and in the root projects' build.gradle
repositories {
mavenLocal()
}
dependencies {
compile group: 'org.gradle'
}
A problem occurred evaluating root project 'root'.
Could not find method compile() for arguments [{group=org.gradle}] on root project 'root'.
Edit 3
I have 2 files:
buildSrc/src/main/groovy/com/iggy/gradle/A.groovy:
package com.iggy.gradle
String someA() {
return "a"
}
buildSrc/src/main/groovy/com/iggy/gradle/B.groovy:
package com.iggy.gradle
String someB() {
String a = someA()
return a
}
But I get an error: Could not find method someA()
Shouldn't methods from same package be resolved? Adding #PackageScope or public doesn't help. So how can one import a method from another groovy file?

Do gradle configurations merge or override?

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.

Resources