Gradle default directory - gradle

We just setup new Linux systems and our gradle builds fail on the new system. If I add the following code to our build.gradle file it give back the location of the gradle daemon folder.
File f = new File(".");
println("\n\n\nCurrent Dir : " + f.getAbsolutePath() + "\n\n");
On our older systems it gives the project root dir. I can't figure out why we're seeing this on the new boxes but not the old ones. Any ideas?

Related

Duplicate generated class gradle output (build/...) vs intellij output (out/...)

I'm using intellij (2019.1.1) for a java gradle (5.4.1) project and use lombok (1.18.6) for autogenerating code. Intellij puts generated sources under out/production/classes/generated/... and gradle puts them under build/generated/sources/...
This is fine, and I like that intellij keeps it's own build artifacts separate from gradles, however, intellij seems to look in both directories when running projects and it complains about the duplicate generated classes.
What is the best practice for using intellij with gradle and autogenerated sources? Do you:
tell intellij to output to the same directory as gradle (this
could lead to odd behaviour if a process outside of intellij updates
a file under build/)
tell intellij to perform all tasks with
gradle (i hear this is slower than intellij's make)
tell intellij
to simply ignore the 'build' directory (how do you even do this? and
why does intellij even care about 'build/' when it knows it outputs
to 'out/')
UPDATE: to clarify the situation, the issue is NOT with lombok autogenerated code, it is with hibernate-jpamodelgen. The problem remains the same (duplicate generated sources) but I want to clarify the it is the sources generated by jpamodelgen and not lombok.
UPDATE 2: I have tried the following configuration in an attempt to tell intellij where the generated sources live and also to tell intellij to ignore the build directory. Sadly, this did not work (still get duplicate class error on the generated source files).
apply plugin: 'idea'
idea {
module {
sourceDirs += file('out/production/classes/generated')
generatedSourceDirs += file('out/production/classes/generated')
excludeDirs += file('build')
}
}
UPDATE 3:
Tried the advice from M.Riccuiti and deleted build/, out/, .idea/, .gradle/ and reimported the gradle project but intellij is still seeing the generated sources in the build/ directory.
Here is an approach that finally worked for me. The trick is to notice that when gradle generates the classes, it puts them in:
build\generated\sources\annotationProcessor\java\main\com...
but intellij has the production sources directory set to "generated" in this case, the sources go to:
build\generated\sources\annotationProcessor\java\main\generated\com...
if you compile with gradle first and then use idea, you get both of them, which causes the problem!
To solve this, replace "generated" and "generated_test" in the intellij annotation processors "production sources directory " and "test sources directory " configuration with just a "/" this makes both gradle and intellij generate the sources in the SAME directory, overwriting each other as needed. Also make sure that the "store generated sources relative to" is set to "module content root" and REBUILD the application to clear out any other sources.
The solution I proposed in previous comment was working fine in IDEA 2018.3.x but after upgrading to IDEA 2019.1 I again got this duplicate class exception...
Below is a working solution to make this work with Gradle 5.x (tested with 5.4) and IDEA 2019.1 , to implement your solution #3 which I think is the best option (do not mix gradle & idea generated output directories, and do not delegate IDEA action do Gradle )
The key point is to use excludeDirs property from idea.module extension to make IDEA ignore generated sources managed by Gradle under build/generated/sources/...
ext {
// path to Gradle generated main sources directory
gradleGeneratedMainSourcesDir = "$buildDir/generated/sources/annotationProcessor/java/main/"
// path to Gradle generated test sources directory
gradleGeneratedTestSourcesDir = "$buildDir/generated/sources/annotationProcessor/java/test/"
// path to IDEA generated sources directory
ideaGeneratedSourcesDir = "$projectDir/out/production/classes/generated"
}
idea {
module {
// exclude main & test sources generated by Gradle from project source directories
excludeDirs += file(gradleGeneratedMainSourcesDir)
excludeDirs += file(gradleGeneratedTestSourcesDir)
// include generated sources directory managed by IDEA
sourceDirs += file(ideaGeneratedSourcesDir)
generatedSourceDirs += file(ideaGeneratedSourcesDir)
}
}
See complete sample project based on this configuration here : https://github.com/mricciuti/sample-springboot-gradle-idea
You can enter to IntelliJ Settings (Preferences):
Preferences | Build, Execution, Deployment | Build Tools | Gradle | Runner
Then you tick the checkbox Delegate IDE build/run action to Gradle
Finally, you clean and build again. The issues will be resolved.

Gradle Idea Plugin Respect Gradle Configuration

The simple question;
Is there a way to make Intellij respect gradle configuration?
The details;
I created a new sourceSets called integrationTest
sourceSets {
integrationTest{
java.srcDir 'src/integration/java'
resources.srcDir 'src/integration/resources'
}
}
I added the new source set to Intellij testSourceDirs
idea {
module {
testSourceDirs += file('src/integration/java')
}
}
Everything works fine from Gradle perspective locally and on CI.
Now I don't want Intellij to create out directory which duplicates build dir I want Intellij to respect and follow gradle configuration as follows:
Source directory main/java should be compiled to classes/java/main
Source directory test/java should be compiled to classes/java/test
Source directory integrationTest/java should be compiled to classes/java/integrationTest
Resource directory main/resources should be compiled to resources/main
Resource directory test/resources should be compiled to resources/test
Resource directory integrationTest/resources should be compiled to `resources/integrationTest
The only solution I found so for (here) is to have
All source directories (in my case I have only one at main/java) and resource directories goes to classes/java/main.
All test directories (in my case I have two at test/java and integrationTest/java) and resource direcotries (in my case I have two at test/resources and integrationTest/resources) goes to classes/java/test; and this is so wrong I need now to pay attention to file names and location not to override each other.
Gradle Version: 4.5
Intellij Version: 2017.3
Update Jan 2021 This is not relevant anymore. It is working fine with newer Intellij. I personally tested with latest version 2020.3.2 Community edition.

Gradle - paths in multi-project builds

I have a multi-project gradle project with following directory structure:
+ project_root
+ module1
+ src
build.gradle
+ module2
+ src
build.gradle
+ web
..
build.gradle
settings.gradle
In module1/build.gradle among other things I have specified:
compileKotlin2Js.kotlinOptions {
outputFile = "web/script.js"
}
It is a special Kotlin JS setting that specifies output file path of compiled JS file.
Now my problem is, that when I build the whole project (project_root/build.gradle) the file ends up in the right directory (project_root/web), but when I accidentally run build on the module alone the file is saved in module directory (project_root/module1/web).
How can I fix paths in my build scripts, so file output will be saved in exactly the same directory no matter which build script I run (without specifying full path, I want a relative path)?
I don't know what Gradle plugin requires the path parameter in your code example, but all regular (non-3rd-party) Gradle plugins evaluate path parameters via Project.files(Object...) to avoid different locations when calling Gradle from various working directories.
I would suggest to use the above method (or its single file version Project.file(Object)) as well. You can even omit the project part, because the build.gradle file gets executed in the project scope:
compileKotlin2Js.kotlinOptions {
outputFile = file('web/script.js')
}
This will always evaluate the path relative to the project directory of the project your build.gradle belongs to. To evaluate a file relative to the project directory of the root project, use rootProject.files(Object...), for a path relative to the project directory of a subproject or any project in the build, use project(':path:to:project').files(Object...).

Gradle: getting the root project directory path when starting with a custom build file

The structure of my Gradle project is the following:
Project
├── app
└── build.gradle
├── foo
└── bar.txt
·
·
·
└── build.gradle
Normally to get the absolute path of the foo folder I can just simply do new File('foo').getAbsolutePath() in the root build.gradle file.
But this unfortunately doesn't work if you run the gradle script from outside the project directory, for example doing something like this:
$ trunk/gradlew -b trunk/build.gradle tasks
With the previous command gradle is looking for the foo directory in the parent of the Project, because I started the script from there.
Is there a way to get the absolute path of the Project where the build.gradle is, even if you start your script from another directory? Or is there any other way to get a reference of a directory in the same folder where the script is?
I've tried also with getClass().protectionDomain.codeSource.location.path but it is returning the path to the gradle cache directory.
I got past this problem by ensuring Java userDir was set to the project directory (i.e. project.projectDir) at the top of my build.gradle file, as follows:
System.setProperty( "user.dir", project.projectDir.toString() )
println " project dir: "+ System.getProperty("user.dir");
This can be checked by executing a separate (Groovy) code file such as:
println "User Dir: ${System.getProperty( 'user.dir' )}"
You can output the Gradle project values before and after using these statements.
println "Root project: ${project.rootProject}";
println " rootDir: ${project.rootDir}"
println " projectDir: ${project.projectDir}";
println " project dir: ${System.getProperty("user.dir")}";
If you have sub-projects, projectDir is not the same as rootDir.
This hasn't fixed my actual problem but it has ensured that I'm opening the correct file (relative to the location of build.gradle.
new File('foo') by definition (look at its JavaDoc) makes a path relative to the current working directory, so depends on where you call the app from. If you want a path relative to the project folder, use project.file('foo'), or as project is the default for resolving the method just file('foo') and you get the relative path resolved against the project directory, not the working directory. So use file('foo').absolutePath and you will be fine.
In the build.gradle file just use projectDir to get the absolute path of the build.gradle file. from there you can navigate your project's files. read this for more info:
https://www.tutorialspoint.com/gradle/gradle_build_script.htm
I was using new File() and path to get the source directory into the gradle file but in Macbook with M1 Chip it's not working, let me share the code for previous and new version:
Older code:
new File("app/src/")
Updated code:
new File(project.projectDir.getAbsolutePath() + "/src/")

Why gradle jars are written in `build/libs`?

According to the documentation of the Jar plugin, the output directory is controlled by the destinationDir property:
File destinationDir
The directory where the archive is generated into.
Default with java plugin: project.distsDir
Looking at the documentation of the Project class the same property is mentioned:
Properties added by the java plugin
distsDir: The directory to generate TAR and ZIP archives into.
distsDirName: The name for the distributions directory. This in interpreted relative to the project' build directory.
And Googling a bit I find a document specifying their defaults:
File distsDir (read-only)
The directory to generate TAR and ZIP archives into.
Default with java plugin: ${project.buildDir}/${project.distsDirName}
String distsDirName
The name for the distributions directory. This in interpreted relative
to the project' build directory.
Default with java plugin: 'distributions'
All these documents point to the same Gradle version, that matches the one I have installed.
I add this in my build.gradle to check the real values of these properties:
println("distsDirName = " + project.distsDirName)
println("distsDir = " + project.distsDir.toString())
jar {
println("jar.destinationDir = " + destinationDir)
}
And finally, I run ./gradlew and check the output:
distsDirName = distributions
distsDir = /home/ntrrgc/myProject/build/distributions
jar.destinationDir = /home/ntrrgc/myProject/build/libs
Why does jar.destinationDir not respect its documented default?
I think, #Alicia is right in pointing out that currently the documentation of the Gradle Jar plugin is providing wrong information in the default value for the File destinationDir:
File destinationDir
The directory where the archive is generated into.
Default with java plugin:
project.distsDir
where default of distsDir is 'build/distributions' as can be here.
In my opinion, it should be
File destinationDir
The directory where the archive is generated into.
Default with java plugin:
project.libsDir
where default of libsDir is 'build/libs' as can be seen here again.
I have opened Gradle issue #1086 for this. Let us see, what they answer.

Resources