I hava an example java project package
package com.example.testing;
with such file tree
app
|
src->com->example->testing->Main.java
and a gradle script:
apply plugin: 'java'
apply plugin: 'application'
sourceSets {
main {
java {
srcDirs 'src'
}
}
}
sourceSets.main.output.classesDir = file("classes")
mainClassName = 'com.example.testing.Main'
defaultTasks 'compileJava', 'run'
Now I want to add some module to this project and my folders will be something like this
app
|
src1->com->example->testing->Main.java
src2->com->another_example->another_testing->Library.java
How do I add new source code to gradle script?
I agree with #JB Nizet about respecting standard conventions. If you still insist on being an Anarchist though:
You already have src declared in your sourceset, why not add src1 and src2 as well? You can add them to the same sourceset, or define a sourceset per module if you want.
sourceSets {
main {
java {
srcDirs 'src'
srcDirs 'src1'
srcDirs 'src2'
}
}
}
To reference files outside the project, see this answer.
The question is about "Adding"; the question of the text is describing a more concrete scenario. If one just wants to add an existing directory, this is the way to add:
sourceSets.main.java.srcDirs += ['src/gen/java']
An example full build.gradle is as follows:
apply plugin: 'java'
repositories {
mavenCentral()
}
dependencies {
implementation 'com.squareup:javapoet:1.12.1'
}
sourceSets.main.java.srcDirs += ['src/gen/java']
JavaPoet s a Java API for generating .java source files. It is just used as example library for the build.gradle file.
I have a slightly different approach with a Gradle 4.6:
sourceSets {
main {
java {
srcDir 'src/main/java'
srcDir 'build/swagger-code-dummy/src/main/java'
}
}
}
as you can see, I had to specify the directories with the "/main/java" subdirectories as well, otherwise gradle/intellij was not setting the right path.
Maybe this helps someone else too :)
A slightly different solution:
sourceSets.main.java.srcDirs = ['build/jasper', 'src/main/java']
Related
I'm unable to add custom source set in my gradle project. How to initialize the version numbers in here?
My gradle file looks like:
plugins {
id 'java'
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
sourceSets {
demo
}
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
}
test {
useJUnitPlatform()
}
You can set custom sourceSets like this in your build.gradle
main {
java {
srcDirs = ['src/gen/java', 'src/main/java']
}
}
The srcDirs is an array, so you can specify more than one source directory.
You can also specify custom source directories for your tests
test {
java {
srcDirs = ['src/integrated-test/java', 'src/test/java']
}
}
You can find some more info here https://www.baeldung.com/gradle-source-sets in section 3. They use the example for integrated tests, but the idea is the same.
Here is the official gradle document for source sets https://docs.gradle.org/current/dsl/org.gradle.api.tasks.SourceSet.html
I found a solution.
If your requirement is projectFolder/src/ -> Here you want to create a custom module other than the main and test. follow the below one.
Its worked in Intellj ide.
sourceSets {
customModuleName.java.srcDir "src/customModuleName"
customModuleName.resources.srcDir "src/customModuleName"
}
// After adding the above block in build file. Go ahead and create a directory, it will show a module name in suggestion
// Then inside module, Go to create a package. Here we can find java and resources folder in suggestion
I am converting over to using IntelliJ (version 2019.1). The multi-project directory structure used has the standard src/main/java and src/test/java for each project, but additionally has some non-standard ones such as: src/testsupport/java.
Gradlew (using the internal/recommended gradlew packaged within IntelliJ) is used to import the projects. The Gradle build files include both:
apply plugin: 'idea'
apply plugin: 'java'
Edited to improve clarity
Every project imports fine. Interproject references work to the standard directories. However, when I am in Project B, but need access to src/generated/java or src/testsupport/java from Project A, those are not imported (import statements that compile fine from the gradle command line show up as unresolvable within IntelliJ). Is there a configuration change or something needed to make these take effect?
Currently, I have:
subprojects {
idea {
module {
testSourceDirs += project.sourceSets.generated.java.srcDirs
testSourceDirs += project.sourceSets.testsupport.java.srcDirs
}
}
}
You need help Gradle out by creating a source set for the custom sources your projects define. So from your question, something like:
(using Kotlin DSL)
allprojects {
apply {
plugin("idea")
plugin("java-library")
}
repositories {
mavenCentral()
}
configure<SourceSetContainer> {
create("generated") {
compileClasspath += project.the<SourceSetContainer>()["main"].output
runtimeClasspath += project.the<SourceSetContainer>()["main"].output
}
create("testsupport") {
compileClasspath += project.the<SourceSetContainer>()["main"].output
runtimeClasspath += project.the<SourceSetContainer>()["main"].output
}
}
val api by configurations
val testImplementation by configurations
val testRuntimeOnly by configurations
dependencies {
api(platform("org.junit:junit-bom:5.5.1"))
testImplementation("org.junit.jupiter:junit-jupiter-api")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
}
val test by tasks.getting(Test::class) {
useJUnitPlatform()
}
}
The above will give you:
So now you want to use projectA in projectB, so projectB's Gradle file would include a dependency on projectA:
dependencies {
implementation(":projectA")
}
This should hopefully get you started. Keep in mind, the examples given above use the Kotlin DSL which you should be able to convert back to Groovy.
References:
https://docs.gradle.org/current/userguide/java_plugin.html#source_sets
https://docs.gradle.org/current/userguide/java_testing.html#sec:configuring_java_integration_tests
I am trying to convert my project to gradle and unable to get the class files generated under build folder. Here is the build.gradle file:
import org.gradle.internal.os.OperatingSystem;
apply plugin: 'java'
sourceCompatibility = 1.8
targetCompatibility = 1.8
sourceSets {
main {
java {
srcDirs = ["abc/def/"]
include('include/Constants.java')
}
}
}
task initial(type: Exec) {
doFirst {
println 'Started compiling constants'
}
if(OperatingSystem.current().isWindows()) {
println 'Compiling on windows'
//Run some bash script here
}
else {
print 'Compiling on unix'
//Run some shell script here
}
doLast {
println 'Finish compiling constants'
}
}
jar {
baseName = 'output'
}
dependencies {
compile files('../lib/log4j/log4j.jar')
compile files('../lib/findbugs/findbugs.jar')
compile files('../lib/guava/guava-19.0.jar')
}
When i do gradle build, it says successfull, but see no classes generated under build folder.
Any help?
Fixed it after some debugging. The issue was the include after the srcDirs did not work as the path was one level higher than the path defined in srcDirs.
I had a similar issue the other day, it was not generating the compiled classes when I run the build on IntelliJ or even on the terminal.
After trying a lot of things what solved the issue was deleting the .gradle directory and running again a ./gradlew clean build.
It was a weird one, but I hope it might help to someone having the same issue.
I created a small library project with the following build.gradle:
apply plugin: 'java'
apply plugin: 'gwt-base'
apply plugin: 'eclipse'
buildscript {
repositories {
mavenCentral()
jcenter()
maven {
url new File(rootProject.projectDir.parentFile, 'repo').toURI()
// url "https://oss.sonatype.org/content/repositories/snapshots/"
}
}
dependencies {
classpath 'de.richsource.gradle.plugins:gwt-gradle-plugin:0.6'
}
}
gwt {
gwtVersion='2.7.0'
}
The folder structure looks like this:
/library
/library/Library.gwt.xml
/library/client/HelloWorldWidget.java
The sources are taken from here.
When I perform a gradle buildgradle generates a jar file which does not contain the sources and also does not contain the gwt.xml module file.
How can I force gradle to include the sources and the gwt.xml file in the generated jar?
Here is the solution to include the *.java files use:
jar {
from('src/main/java') {
include '**/*.java'
}
}
The include any other resources like gwt.xml files put them into:
/src/main/resources
Alternatively you can use:
jar {
from project.sourceSets.main.allSource
from project.sourceSets.main.output
}
When using the Java plugin, Gradle assumes that the project has the standard structure, i.e. 'src\main\java' & 'src\test\java'. Therefore when executing the build tasks it simply doesn't find any of those directories.
The best way to fix this will be to define your project structure by modifying the existing source sets, which define where your sources are:
sourceSets {
main {
java {
include '/library/**'
}
}
test {
java {
include '/test/sources/directory/**'
}
}
}
As for now we have a project structure with single source folder named src, which contains source code for three modules. What I want to do is:
1) Compile source code. This is easily done with sourceSets definition:
sourceSets {
main {
java {
srcDir 'src'
}
}
}
2) Put compilation results into three jars. I am doing this via three 'jar' type tasks:
I am doing this now via three separate tasks:
util.jar
task utilJar(type: Jar) {
from(sourceSets.main.output) {
include "my/util/package/**"
}
}
client.jar
task clientJar(type: Jar) {
from(sourceSets.main.output) {
include "my/client/package/**"
}
}
server.jar
task serverJar(type: Jar) {
from(sourceSets.main.output) {
include "**"
}
excludes.addAll(utilJar.includes)
excludes.addAll(clientJar.includes)
}
The thing is that server.jar should contain all classes that are not contained within client.jar and util.jar. In ant build script we solve this problem by using difference ant task. How this can be done in gradle (my current approach doesn't work)?
Maybe my approach is completely wrong. Please advice.
P.S. as for now we CAN NOT change the project source code folder structure.
I will post my working solution here as an answer (I've got a hint on gradle's forum).
The scopes in gradle are very strange thing :) I thought that every task definition creates an object of some 'Task' class, which is something like 'JarTask' in this particular case. Then I can access any property of the class from anywhere in my build.gradle script. However, I found the only place where I can see the patterns, which are included in jar file - inside a from block of a task. So my working solution for now is to:
1) Define a project-level collection to contain patterns to be excluded from server.jar
2) Exclude all patterns in from block of serverJar task.
Please see final version below
sourceSets {
main {
java {
srcDir 'src'
}
}
}
// holds classes included into client.jar and util.jar, so they are to be excluded from server.jar
ext.serverExcludes = []
// util.jar
task utilJar(type: Jar) {
from(sourceSets.main.output) {
include "my/util/package/**"
project.ext.serverExcludes.addAll(includes)
}
}
// client.jar
task clientJar(type: Jar) {
from(sourceSets.main.output) {
include "my/client/package/**"
project.ext.serverExcludes.addAll(includes)
}
}
// server.jar
task serverJar(type: Jar) {
from(sourceSets.main.output) {
exclude project.ext.serverExcludes
}
}
I think the approach is wrong. I recommend making a project with 3 sub projects.
project
- util
- server (depends on util)
- client (depends on util)
If for some reason you cannot change the class structure use this kind of build files:
settings.gradle
include 'util', 'client', 'server'
build.gradle
subprojects {
apply plugin: 'java'
}
project(':util') {
sourceSets {
main {
java {
srcDir '../src'
include 'util/**'
}
}
}
}
project(':server') {
sourceSets {
main {
java {
srcDir '../src'
include 'server/**'
}
}
}
dependencies {
compile project(':util')
}
}
project(':client') {
sourceSets {
main {
java {
srcDir '../src'
include 'client/**'
}
}
}
dependencies {
compile project(':util')
}
}
You still need directories for subprojects but the sources are in one place as you wanted.
When you run gradle assemble you will have 3 jars with separate set of classes. The advantage of this solution is that we make a proper Gradle multi module project with correct dependencies, not just tasks for building jars.
Please read Multi-Project Builds.
We have the same problem at my company, ie. legacy code that is difficult to migrate into a "good" project structure, and the need to build several jars from the same codebase. We decided to define different sourceSets and build each of the sourceSets using standard Gradle.
We then use iterators to add jar- and javadoc-tasks for each sourceSet:
sourceSets.all { SourceSet sourceSet ->
Task jarTask = tasks.create("jar" + sourceSet.name, Jar.class)
jarTask.from(sourceSet.output)
// Configure other jar task properties: group, description, manifest etc
Task javadocTask = tasks.create("javadoc" + sourceSet.name, Javadoc.class)
javadocTask.setClasspath(sourceSet.output + sourceSet.compileClasspath)
javadocTask.setSource(sourceSet.allJava)
// Extra config for the javadoc task: group, description etc
Task javadocJarTask = tasks.create("javadocJar" + sourceSet.name, Jar.class)
javadocJarTask.setClassifier("javadoc") // adds "-javadoc" to the name of the jar
javadocJarTask.from(javadocTask.outputs)
// Add extra config: group, description, manifest etc
}
I agree in principal with the accepted answer too.
I found a project where the client requires two JAR essentially of the same file except the Manifest is different only by the Class-Path key.
jar {
manifest {
attributes(
"Main-Class": platformMainClass,
"Implementation-Title": platformDisplayName,
"Implementation-Description": platformDescription,
"Platform-Version": platformVersion,
"Implementation-Version": version,
"Build-Assembly-User": System.getProperty("user.name"),
"Build-Assembly-Date": new java.util.Date().toString(),
"Class-Path": configurations.compile.collect { "lib/"+it.getName() }.join(' ')
)
}
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
exclude( [ 'log4j*.properties', 'uk/gov/acme/secret/product/server/**' ])
}
The same manifest and the source code then is:
task applicationClientJar(type: Jar, description: "Creates the Application Client JAR file.") {
dependsOn compileJava
manifest {
attributes(
"Main-Class": platformMainClass,
"Implementation-Title": platformDisplayName,
"Implementation-Description": platformDescription,
"Platform-Version": platformVersion,
"Implementation-Version": version,
"Assembly-Date": new java.util.Date().toString()
)
}
archiveName = "acme-client-${platformVersion}.jar"
destinationDir = file("${buildDir}/libs")
from sourceSets.main.output
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
exclude( [ 'log4j*.properties', 'uk/gov/acme/secret/product/server/**' }
So Grzegorz notation is correct, because the Gradle should know there are two different JAR with GAVs. Multi-module is the preferred option.
compile "uk.gov.acme.secret:acme:1.0" // CORE
compile "uk.gov.acme.secret:acme-client:1.0"
The only way to configure for this is to use the Multi-Module Gradle project and then add a compile and/or deploy dependency to the core / main project.
project(':common:acme-micro-service-webapp') {
dependencies {
compile project(':common:acme-core')
}
}
Inside the 'acme-micro-service-webapp' project, this ensures that the dependent 'common:acme-core' is compiled first.
PS: I am still trying to figure out a better solution.
PS PS: If you are using Maven as well as, it may be possible to hook on the `install' task.