Get project name of task in gradle - groovy

I have a multi-project build. Sub-projects are in tree structure (not flat).
In root build.gradle file I have a method that does some common thing for compilation phase.
I would like to have separate target dir for each subproject. So when I'm compiling whole project I will have own artifacts for each subproject.
Method I mentioned above does compilation, so it needs to know which project it compiles.
If I use "gradle :subproject1:subsubproject1:compile" command then project.name still contains root project name. But I need in runtime to know project of task that called for method.
Questions are:
Is it good idea at all to have separate targets for subprojects?
How can I understand project of task that called for method inside this method?

If the task is defined in the subproject then you can simply use project.name to get the name of the project the task is run under.
You can try it out, for example by adding the following code to build.gradle located on the root project:
allprojects {
task printProjName << {
println ">> " + project.name
}
}
Then, executing the printProjName task will result in an output similar to the one below:
:printProjName
>> Gradle
:projA:printProjName
>> projA
:projB:printProjName
>> projB
:projA:projA1:printProjName
>> projA1
:projA:projA2:printProjName
>> projA2

Related

Writing a gradle task to run Junits

I am a newbee to gradle. The task at hand is to add a new gradle task that can run all the junits in the project and show a summary like which testcases passed, failed,skipped etc.
gradle version used is 4.8.1 and junit4.11
The project structure is like this:
Myproject
|_____api
| |_____src
| |_____main
| |_____test
| |____java
|_____cli
|_____src
|_____main
|_____test
|____java
I am able to run the individual tests from intelliJ.
There is a "test" method defined in the build.gradle of "cli" but I am not sure it runs. With command "gradle clean test" the build is successfull but I see no test results.
test {
include '*/cli/src/test/java/testsuites/*'
exclude '*/cli/src/test/java/com/myproject/mytool/*'
}
I have tried to add dependency and other things that I got from googling and at stackoverflow but of no use.Nothing seems to be working out.Can anyone help me to understand the basic steps and checks that I need to follow to create a gradle task for running junits? any help is appriciated.

Build - Make module/project uses wrong build type

As long as I used android studio 3.1 everything was working fine. But after the recent update to 3.2 I see following behaviour:
calling "build"/"make module" leads to execution of Executing tasks: [assemble]
calling "build"/"make project" leads to the same, assemble task is executed as well
Before the update I was able to exectue the correct assemble task (like assembleDebug<...>).
Does anyone know where I can correct this? Can I somehow check which task is bound to those menus and edit them? I have this problem with one project only...
Currently I have to manually execute the gradle task to get what I want, menu entries seem to be broken...
Setup
I am using flavours
I have selected a build variant of debug type, all my modules are set to debug as well:
apps build variant: devWithoutTestWithAccessibilityDebug
all other modules build variant: debug
Current solution
I use my own gradle tasks for my most common development build like following for now:
task runDev (type: Exec, dependsOn: 'installDevWithoutTestWithAccessibilityDebug') {
commandLine android.getAdbExe().toString(), "shell",
"monkey",
"-p", "com.my.app.debug",
"-c", "android.intent.category.LAUNCHER", "1"
}
What I tried
Clean project like following:
delete ALL *.iml files
delete .gradle and .idea folder
delete all temp files
import project again
sync project with gradle files
create app run configuration again and start it
Still I end with the same result...

Gradle complains "No such file or directory"

I am using Android Studio & Gradle build script.
Under the root of my Android project, there is a folder named 'other', inside 'other' folder, there is a properties file my.properties.
-MyApp/
…
-other/
-my.properties
-build.gradle
In my build.gradle, I try to access my.properties :
task accessMyProperties {
def folderName = 'other';
//Gradle complains this line
def file = new File("$folderName/my.properties");
...
}
But gradle complains that:
* What went wrong:
A problem occurred evaluating project ':MyApp'.
> other/my.properties (No such file or directory)
Why gradle arises the above error? How to get rid of it?
Be careful about using pure relative paths in Gradle build scripts; those rely on the working directory at the time the build is invoked, which isn't something you should depend on. It's much better to ground your paths against $projectDir or $rootDir. Try something like this:
def file = new File("$projectDir/$folderName/my.properties");
See http://www.gradle.org/docs/current/dsl/org.gradle.api.Project.html for a list of variables you can use.

how to export a executable jar in gradle, and this jar can run as it include reference libraries

how to export a executable jar in gradle, and this jar can run as it include reference libraries.
build.gradle
apply plugin: 'java'
manifest.mainAttributes("Main-Class" : "com.botwave.analysis.LogAnalyzer")
repositories {
mavenCentral()
}
dependencies {
compile (
'commons-codec:commons-codec:1.6',
'commons-logging:commons-logging:1.1.1',
'org.apache.httpcomponents:httpclient:4.2.1',
'org.apache.httpcomponents:httpclient:4.2.1',
'org.apache.httpcomponents:httpcore:4.2.1',
'org.apache.httpcomponents:httpmime:4.2.1',
'ch.qos.logback:logback-classic:1.0.6',
'ch.qos.logback:logback-core:1.0.6',
'org.slf4j:slf4j-api:1.6.0',
'junit:junit:4.+'
)
}
after i run : gradle build
it create the build folder, and i run the jar in build/libs/XXX.jar:
java -jar build/libs/XXX.jar
here is a execution says :
Exception in thread "main" java.lang.NoClassDefFoundError: ch/qos/logback/core/joran/spi/JoranException
how can i run it with the reference libraries?
You can achieve it with Gradle application plugin
Hopefully this helps someone (as I unfortunately spent quite some time trying to find the solution). Here's the solution that worked for me for creating an executable JAR. I'm embedding Jetty in the main method, Jetty 9 to be specific and using Gradle 2.1.
Include the following code into your build.gradle file (if a subproject is the "main" project that the jar needs to be built from, then add it to the subproject which should start like this project(':') { insert the code somewhere here, after dependencies.}.
Also, you need to add the plugin java for this to work: apply plugin: 'java' .
My jar task looks as follows:
apply plugin: 'java'
jar {
archiveName = "yourjar.jar"
from {
configurations.runtime.collect {
it.isDirectory() ? it : zipTree(it)
}
configurations.compile.collect {
it.isDirectory() ? it : zipTree(it)
}
}
manifest {
attributes 'Main-Class': 'your.package.name.Mainclassname'
}
exclude 'META-INF/*.RSA', 'META-INF/*.SF','META-INF/*.DSA'
}
And then you can execute your yourjar.jar via the commandline:
java -jar yourjar.jar
The META-INF/.RSA, META-INF/.SF and META-INF/*.DSA have to be excluded for it to work. Otherwise a SecurityException gets thrown.
The problem seems to lie with embedded Jetty, as Jetty moved to Eclipse and now is signing their JARs, which I read becomes problematic when other, unsigned JARs want to load the signed ones. Please feel free to educate me if I am wrong in this, that's just what I read.
The JARs that the project depends on are defined in the dependencies as follows:
dependencies {
// add the subprojects / modules that this depends on
compile project(':subproject-1')
compile project(':subproject-2')
compile group: 'org.eclipse.jetty', name: 'jetty-server', version: '9.2.6.v20141205'
compile group: 'org.eclipse.jetty', name: 'jetty-servlet', version: '9.2.6.v20141205'
compile group: 'org.eclipse.jetty', name: 'jetty-http', version: '9.2.6.v20141205'
}
EDIT: Before, instead of just
configurations.runtime.collect{...}
i had
configurations.runtime.asFileTree.files.collect{...}
This caused strange behaviour in a larger project in clean build. When running the jar after executing gradle clean build for the first time (after manually cleaning the build directory), it would throw a NoClassDefFoundException (in our project with many subprojects), but running the jar after executing gradle clean build a second time (without emptying the build directory manually), for some reason it had all dependencies. This didn't happen if asFileTree.files was left out.
Also I should note, all compile dependencies are included in runtime, however not all runtime are included in compile. So if you are just using compile
configurations.compile.collect {
it.isDirectory() ? it : zipTree(it)
}
Then be sure to remember that if there is a NoClassDefFoundException thrown, some class isn't found at runtime, which means you should also include this:
configurations.runtime.collect {
it.isDirectory() ? it : zipTree(it)
}
Quick answer
Add the following to your build.gradle:
apply plugin: 'application'
mainClassName = 'org.example.app.MainClass'
jar {
manifest {
attributes 'Main-Class': mainClassName,
'Class-Path': configurations.runtime.files.collect {"$it.name"}.join(' ')
}
}
From the project directory, run gradle installDist
Run java -jar build/install/<appname>/lib/<appname>.jar
I recommend adding the app version to your build.gradle as well, but it's not required. If you do, the built jar name will be <appname>-<version>.jar.
Note: I'm using gradle 2.5
Details
In order to create a self contained executable jar that you can simply run with:
java -jar appname.jar
you will need:
your jar to include a MANIFEST file pointing to your application main class
all your dependencies (classes from jars outside of your application) to be included or accessible somehow
your MANIFEST file to include the correct classpath
As some other answers point out, you can use some third-party plugin to achieve this, such as shadow or one-jar.
I tried shadow, but didn't like the fact that all my dependencies and their resources were dumped flat out into the built jar together with my application code. I also prefer to minimize the use of external plugins.
Another option would be to use the gradle application plugin as #erdi answered above. Running gradle build will build a jar for you and nicely bundle it with all your dependencies in a zip/tar file. You can also just run gradle installDist to skip zipping.
However, as #jeremyjjbrown wrote in a comment there, the plugin does not create an executable jar per se. It creates a jar and a script which constructs the classpath and executes a command to run the main class of your app. You will not be able to run java -jar appname.jar.
To get the best of both worlds, follow the steps above which create your jar together with all your dependencies as separate jars and add the correct values to your MANIEST.
All of these answers are either wrong or out of date.
The OP is asking for what is known as a "fat jar". That is an exectuable jar which contains all the dependencies so that it requires no outside dependencies in order to run (except for a JRE of course!).
The answer at the time of writing is the Gradle Shadow Jar plugin, explained pretty clearly at Shadow Plugin User Guide & Examples.
I struggled a bit. But this works:
put all these lines somewhere in your build.gradle file (I put them near the top) :
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.4'
}
}
apply plugin: 'com.github.johnrengelman.shadow'
shadowJar {
baseName = 'shadow'
classifier = null
version = null
}
jar {
manifest {
attributes 'Class-Path': '/libs/a.jar'
attributes 'Main-Class': 'core.MyClassContainingMainMethod'
}
}
PS don't worry about any other "repositories", "dependency" or "plugin" lines elsewhere in your build file, and do leave the lines thus inside this "buildscript" block (I haven't a clue why you need to do that).
PPS the Shadow Plugin User Guide & Examples is well-written but doesn't tell you
to include the line
attributes 'Main-Class': 'core.MyClassContainingMainMethod'
where I've put it above. Perhaps because the author assumes you are less clueless than I am, and you probably are. I haven't a clue why we are told to put a strange "Class-Path" attribute like that in, but if it ain't broke don't fix it.
When you then go
> gradle shadowjar
Gradle will hopefully build a fat executable jar under /build/libs (default name "shadow.jar") which you can run by doing this:
> java -jar shadow.jar
I checked quite some links for the solution, finally did the below mentioned steps to get it working. I am using Gradle 2.9.
Make the following changes in your build,gradle file :
1. Mention plugin:
apply plugin: 'eu.appsatori.fatjar'
2. Provide the Buildscript:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath "eu.appsatori:gradle-fatjar-plugin:0.3"
}
}
3. Provide the Main Class:
fatJar {
classifier 'fat'
manifest {
attributes 'Main-Class': 'my.project.core.MyMainClass'
}
exclude 'META-INF/*.DSA', 'META-INF/*.RSA', 'META-INF/*.SF'
}
4. Create the fatjar:
./gradlew clean fatjar
5. Run the fatjar from /build/libs/ :
java -jar MyFatJar.jar

Read gradle paths from project

Is there any way to access Gradle groovy plugin sourceSets dirs from my Groovy project built by Gradle? I am looking for default gradle src and resources directories.
I need it to avoid hardcoding a resources directory in my project but use the default Groovy plugin resource directory (resources/main).
You shouldn't mix up your production code with your test sources and your test resources. I would suggest the following layout (the default of the groovy plugin) of your src directories in your project:
groovy production code in "src/main/groovy"
unit tests written in java or groovy in "src/test/groovy"
*.groovy resources for testing your DSL in "src/test/resources"
Now you can reference the .groovy dsl test files from your tests via
URL url = this.getClass().getResource("/testDsl.groovy");
File testDslFile = new File(url.getFile());
Can you explain the use case for that? within your gradle build you can access the groovy sourceSets dirs introduced by Gradles groovy plugin like this:
apply plugin:'groovy'
task printGroovySourceDirs << {
sourceSets.main.groovy.srcDirs.each{
println it.absolutePath
}
}

Resources