Gradle split "src/main/java" and "src/main/kotlin" into submodules - gradle

My project started with a single build.gradle (no multi-project). The project has src/test/java and src/test/kotlin folders.
So far, I have applied the configuration for both projects.
Main problem is the incompatibility with JDK 9 for java submodule and JDK 8 for kotlin submodule. With this error message
Could not target platform: 'Java SE 9' using tool chain: 'JDK 8 (1.8)'.
I want to apply:
only to src/test/java a specific config (sourceCompatibility = 1.9)
same to src/test/kotlin this config (kotlinOptions.jvmTarget = "1.8")
How can I split both folders (java and kotlin) into submodules without moving files ? The folders don't have to be split as submodules. I only want to apply different compilations options.
The project build.gradle is there

Use sourceSets
sourceSets {
test {
kotlin {
srcDirs = ["src/test/kotlin"]
}
java {
srcDirs = ["src/test/java"]
}
}
}

I found an answer how to run in IntelliJ, https://stackoverflow.com/a/58796344/311420
Basically, I was trying to use gradle configuration to run. But the tests fail in Intellij but not in gradle.
Now I run the tests with IntelliJ configurations not gradle.
It is half satisfactory answer.
You can see how my tests in Circle CI and Travis CI

Related

Can't build kotlin files using gradle kotlin DSL in Intellij idea

I'm trying to set up a kotlin project with gradle kotlin DSL as build system in IntelliJ idea,but I'm getting below error when try to run buil.gradle.kts file. I have tried with different kotlin compiler version but no luck.
warning: default scripting plugin is disabled: The provided plugin org.jetbrains.kotlin.scripting.compiler.plugin.ScriptingCompilerConfigurationComponentRegistrar is not compatible with this version of compiler
error: unable to evaluate script, no scripting plugin loaded
IntelliJ Version:
Gradle version : 6.3
build.gradle.kts
plugins {
id("org.jetbrains.kotlin.jvm") version "1.3.70"
// Apply the application plugin to add support for building a CLI application.
application
}
repositories {
// Use jcenter for resolving dependencies.
// You can declare any Maven/Ivy/file repository here.
jcenter()
}
dependencies {
// Align versions of all Kotlin components
implementation(platform("org.jetbrains.kotlin:kotlin-bom"))
// Use the Kotlin JDK 8 standard library.
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
// Use the Kotlin test library.
testImplementation("org.jetbrains.kotlin:kotlin-test")
// Use the Kotlin JUnit integration.
testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
}
application {
// Define the main class for the application.
mainClassName = "Music.AppKt"
}
The correct way to build a Gradle project in IDEA is to execute "Main menu | Build | Build project" if your build is delegated to Gradle in IDEA settings, or execute one of the build tasks in Gradle tool window: http://jetbrains.com/help/idea/work-with-gradle-tasks.html
However, the behavior you described can be considered a usability problem, I created an issue https://youtrack.jetbrains.com/issue/KT-37814, please follow it for updates.

How to get source code directory in Gradle plugin?

I want to get the directory of Java files in a Groovy plugin.
For example, I have a Java file in a directory:
"/gradleProject/src/main/java/com/file.java"
How can I get:
"src/main/java"
In Maven there is Build.getSourceDirectory(), what is the equivalent in Gradle?
Further to Rene's answer, the groovy DSL makes it easy to get the SourceSet
SourceSet mainSourceSet = project.sourceSets.main
In java this is a little bit more verbose
SourceSet mainSourceSet = project.getConvention().getPlugin(JavaPluginConvention.class).getSourceSets().getByName("main");
In Gradle, those source folders are managed by SourceSets, that are brought to you by the Java plugin. The java plugin adds two sourceSets named main and test.
once the java plugin is applied, you can access those sourceSets and their properties (e.g. the folders you're looking) simply by name: project.sourceSets.main.srcDirs - this will give you all the configured source directories for the main sourceSet in your project.
The latest way to do this, using the Kotlin DSL:
val javaExt = project.extensions.getByType(JavaPluginExtension::class.java)
val mainJavaSource = javaExt.sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME)
Using the Kotlin DSL (Gradle 7.5)
tasks.register<JacocoReport>("jacocoTestReport") {
dependsOn("testDebugUnitTest")
val sourceSets = project.extensions.getByType<KotlinProjectExtension>().sourceSets
sourceDirectories.setFrom(sourceSets)
}
Note that besides the JavaPluginExtension there is also a KotlinAndroidProjectExtension, so you may can get rid of the Android Gradle Plugin in your community plugins.

Gradle include jar produced by another project in war

Currently I have two projects with gradle build.gradle. The first is going to create a fat jar file, which I would like to include in a war file. I thought compiling it would be enough, but it doesn't seem to be ending up in the /lib directory of my war file. Anyone have thoughts I am quite new to gradle.
dependencies {
compile project(':JarProject')
providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
providedCompile 'org.apache.tomcat:tomcat-jsp-api:7.0.55'
}
war {
archiveName 'WarProject.war'
from 'JarProject/build/libs'
webXml = file('src/web.xml')
}
Does the second project war need to be in providedRuntime? Or should I publish the jar from the other project in the local maven repo and include it that way?
The War task essentially behaves like a CopyTask with regards to stuff it packs in the war, so the documentation on working with files is useful. In essence, I think you need something like (untested):
from fileTree('JarProject/build/libs') {
into("lib")
}
That being said, using mavenLocal() and publishing there also works, but it can lead to unexpected results when the war includes some old version from local, picking up the jar explicitly from the file system like above is better.
I think the elegant solution would be to use multi project builds and project level dependencies. You would have the two builds as separate projects of the same Gradle build and add the "jar project" as a regular compile dependency.
How have you declared the dependency? I assume you have a multi-project build with subprojects A and B, both using the War plugin. I made an experiment using Gradle 2.4 and if I declare B/build.gradle like this:
apply plugin: 'war'
dependencies {
compile project(':A')
}
then B.war contains WEB-INF/lib/A.jar. If you correctly follow conventions of Gradle War plugin (place web resources in A/src/main/webapp/ and code-related resources in A/src/main/resources/), then A.jar should contain what you want.
see this

Gradle multiproject gives "Could not find property 'sourceSets' on project" error

I had quite good gradle configuration, that built everything just fine. But one of the projects of my multi-project build derived from the rest of them so much, that I would gladly move it to another git repo and configure submodules to handle it.
First, I moved Project and its resources to subfolder Libraries/MovedProject. After altering some lines in gradle configurations it worked fine. But then I decided to write a new build.gradle just for this project, and move all configurations there from the main one.
And this is where everything stopped working. When I try to call any task it always ends
with Could not find property 'sourceSets' on project ':Libraries/MovedProject'. Line which is responsible for it is:
dependencies {
...
if (noEclipseTask) {
testCompile project(':Libraries/MovedLibrary').sourceSets.test.output
}
}
which I use for running tests in which I use classes from other projects. If I remove that line, the build fails only when it reaches compileTestJava task of projects that make use of MovedProject. If I remove that line and call gradle :Libraries/MovedLibrary:properties I can see :
...
sourceCompatibility: 1.7
sourceSets: [source set main, source set test]
standardOutputCapture: org.gradle.logging.internal.DefaultLoggingManager#1e263938
...
while gradle :Libraries/MovedLibrary:build builds correctly.
Currently I've got everything set up as following:
directories:
/SomeMainProject1
/SomeMainProject2
/SomeMainProject3
/Libraries
/MovedProject
build.gradle
dependencies.gradle
project.gradle
tasks.gradle
/Builder
dependencies.gradle
project.gradle
tasks.gradle
build.gradle
settings.gradle
settings.gradle
include Libraries/MovedProject,
SomeMainProject1,
SomeMainProject2,
SomeMainProject3
sourceSets for MovedProject are defined in Libraries/MovedProject/project.gradle:
sourceSets {
main {
java {
srcDir 'src'
srcDir 'resources'
}
resources { srcDir 'resources' }
}
test { java {
srcDir 'test/unit'
} }
}
dependencies that makes use of sourceSets.test.output are stored in Builder/dependancies.gradle, and set for each project that needs MovedProject to run tests:
project(':SomeMainProject1') {
dependencies {
...
if (noEclipseTask) {
testCompile project(':Libraries/net.jsdpu').sourceSets.test.output
}
}
}
What would be the easiest way to get rid of that error and make gradle build projects with current directory structure? I would like to understand why gradle cannot see that property.
The line in question is problematic because it makes the assumption that project :Libraries/MovedLibrary is evaluated (not executed) before the current project, which may not be the case. And if it's not, the source sets of the other project will not have been configured yet. (There won't even be a sourceSets property because the java-base plugin hasn't been applied yet.)
In general, it's best not to reach out into project models of other projects, especially if they aren't children of the current project. In the case of project A using project B's test code, the recommended solution is to have project B expose a test Jar (via an artifacts {} block) that is then consumed by project A.
If you want to keep things as they are, you may be able to work around the problem by using gradle.projectsEvaluated {} or project.evaluationDependsOn(). See the Gradle Build Language Reference for more information.
I had a similar error happen to me in a multimodule project, but for me the cause was as simple as I had forgotten to apply the java-library plugin within the configurations, I only had maven-publish plugin in use.
Once I added the plugin, sourceSets was found normally:
configure(subprojects) {
apply plugin: 'maven-publish'
apply plugin: 'java-library'
....

Gradle 1.2: Exclude directory under resources sourceSets

I have development related directory src/main/resources/certs/test which is needed for one external library. This has some cert files which are not needed in production build.
At the moment I exclude everything under that directory with following block in build.gradle:
sourceSets {
main {
resources {
exclude '**/test/*'
}
}
}
This does it job well, but leaves ugly empty directory test lying there. What are my options to not include this directory in final war?
I've tried excluding '**/test', but it doesn't work at all.
I use war plugin and Gradle 1.2
Using Gradle 1.1, this works for me:
apply plugin: 'war'
sourceSets {
main {
resources {
exclude '**/test/*'
exclude 'certs/test'
}
}
}
I had a similar problem with production files in a JAR file (though mine were not test files). I solved it with the following:
jar {
exclude ("DIRECTORY-TO-EXCLUDE/**")
}
e.g.
jar {
exclude ("test/**")
}
A common projet layout is to put test files under the test source set, this way you don't have to exclude them from the main source set.
From the Gradle documentation, the default project layout is like this:
src/main/java Production Java source
src/main/resources Production resources
src/test/java Test Java source
src/test/resources Test resources

Resources