How to override Gradle `rootProject.name` from the command line? - gradle

I'm writing a test that does a build and publish to Artifactory. Since I don't want the test to fail if it's run concurrently (eg by separate build jobs or developers), I'd like to override rootProject.name. Can this be done from the command line? I've tried -ProotProject.name=${module} and -Pproject.archivesBaseName=${module} but they're not working (the latter does have some effect, but the artifact is still published with the rootProject.name setting in settings.gradle).

You'll have to script settings.gradle. For example:
rootProject.name = System.getProperty("rootProjectName")
Now you can run with gradle build -DrootProjectName=foo.

The following is a slightly simpler version when you need the default behavior that just passes through the default when it's not being overwritten.
rootProject.name = System.getProperty('rootProjectName') ?: rootProject.name

Related

How can I list all transitive dependencies of a multi-project build

I have a multi-project build with a lot of sub-projects.
How can I list all transitive dependencies of the multi-project build.
Ideally, this would be possible with some command line argument, i.e. without modifying any gradle files, and list a nice dependency tree on the command line.
One solution which does modify the parent build.gradle (but minimally) is from this blogpost:
subprojects {
task allDeps(type: DependencyReportTask) {}
}
Since my parent build.gradle has a subprojects section already, this is a one-liner. Furthermore, I can restrict the output by specifying a configuration. Hence this is an acceptable solution, so a command line option would be nicer.
You can use -I (or --init-script) at command line to specify an Init Script
You can then add whatever tasks etc you like in the init script without altering build.gradle

Gradle equivalent for maven properties

How can I add properties in Gradle which are similar to Maven's properties?
The use case is this: I want to have a file which declares all versions for repo dependencies so they are unified in a single place for a multi module project
compile group: 'javax.servlet.jsp.jstl', name: 'jstl', version: '1.2'
In Maven you can have properties like this:
<properties>
<jstlVersion>1.2</jstlVersion>
</properties>
Is it ok to use Gradle's external properties? Or just add them to the gradle.properties file?
Project properties defined in the root build file are available to subprojects. So if you have this in your root build.gradle file:
ext.commonsLangVersion = "2.4"
then you can use that in the dependencies {} block of a subproject like so:
dependencies {
implementation "commons-lang:commons-lang:${commonsLangVersion}"
}
You can also define such properties in the root gradle.properties file instead of the root build file. You use them in the same way.
If you really feel the need to put the versions in a separate file, you can do so. Simply add the following line to the root build file:
apply from: "dependencies.gradle"
Within the dependencies.gradle file, you can define the extra project properties as if they were in the root build file directly:
ext.commonsLangVersion = "2.4"
Note Normally, the values set in the build script take precedence over the values in gradle.properties. But if you set a value in the root build script as above, then any matching value in gradle.properties will override it in subprojects.
This behaviour is somewhat confusing and unique. For behaviour that is consistent with Gradle single-project builds you would need to use the following in the root build script:
allprojects {
apply from: "dependencies.gradle"
}
As a general rule of thumb, any given property should be declared/defined in either the build script or gradle.properties. If users want to override a particular property value, they can do so in $USER_HOME/.gradle/gradle.properties.
[EDIT I have updated the above note to clarify the actual behaviour]
One final thing: Gradle also allows you to control the versions of transitive dependencies via dependency constraints. You can also import Maven BOMs if you're using Gradle 4.6 or newer.
Found this as a possible solution, though I don't really like that uses relative path to the properties file.
Point 7 from here:
https://proandroiddev.com/make-your-build-gradle-great-again-c84cc172a654#8029

How to execute gradle task during project import in Intellij Idea

Let's assume my build.gradle file contains task generateSources which as name suggests generates additional java files. It's easy to ensure that generateSources is executed before compileJava: compileJava.dependsOn generateSources. How can I make sure generateSources is called when importing project into Intellij Idea as well?
To elaborate on #vladimir-sitnikov's answer: I added the idea-ext-plugin to my root project:
apply plugin: 'org.jetbrains.gradle.plugin.idea-ext'
// ...
buildscript {
dependencies {
classpath "org.jetbrains.gradle.plugin.idea-ext:org.jetbrains.gradle.plugin.idea-ext.gradle.plugin:0.7"
}
}
Because without that I wasn't able to use it in my sub project, but now it works like this:
idea.project.settings.taskTriggers {
beforeSync tasks.getByName("generateSources")
}
Adding the plugin to the sub-project only didn't do it.
Note: The plugin's documentation is kind of limited, but in "DSL spec v. 0.2" is stated
beforeSync - before each Gradle project sync. Will NOT be executed on initial import
Didn't try that, but it works with existing projects.
This can be done via id("org.jetbrains.gradle.plugin.idea-ext") plugin (https://github.com/JetBrains/gradle-idea-ext-plugin).
See sample code in Gradle sources: https://github.com/gradle/gradle/blob/135fb4751faf2736c231636e8a2a92d47706a3b9/buildSrc/subprojects/ide/src/main/kotlin/org/gradle/gradlebuild/ide/IdePlugin.kt#L147
You can set the task in Gradle tool window: Execute Before Sync:

How can I share build code script for all my gradle projects (not just subprojects)

I want to have this code snippet
test {
testLogging.showStandardStreams = true
}
Shared for all my gradle projects. Is that possible? Preferrably something I add to ~/.gradle/common.gradle or similar.
Probably the best way to inject build logic into existing build scripts without touching them is using init scripts. So you can create a script like testlogging.gradle that looks like this:
allprojects {
tasks.withType(Test) {
testLogging.showStandardStreams = true
}
}
As you can see I use tasks.withType(Test) instead of test here to reference the test task by type. That has some benefits:
this script works also for builds with no task with name test. This could likely happen (e.g. in multiproject builds)
this script would also apply for any other tasks in your build that are of type Test. Some projects use integTest etc.
To auto apply this script on your machine, you can put it in the folder ~/.gradle/init.d. Gradle considers every .gradle file in there as init script and applies them to each build.
To learn more details about init scripts check the according chapter in the gradle userguide.

How to pass system properties to the tests in gradle in the smart way?

build.gradle
tasks.withType(Test){
systemProperties=System.properties
println systemProperties['param']
}
Now I can either pass parameters in the command line:
gradle test -Dparam=10
or put them in gradle.properties:
systemProp.param=15
Ideally I would like to put the defaults in the gradle.properties, and be able to overwrite them from the command line. Unfortunately if I do that, the gradle.properties has precedence, and -Dparam=10 is ignored.
Could you offer any solutions on that?
https://issues.gradle.org/browse/GRADLE-2122
It works since 2.12 or 2.13 "the smart way" already!
The example above is working, the command line -D option overdrives the defaults in gradle.properties
I am using gradle 2.12 and sharing how I used it:
test {
// support passing -Dsystem.property=value to bootRun task
systemProperties = System.properties
}
I have JUnit tests that I wanted to skip unless a property was used to include such tests. Using JUnit Assume for including the tests conditionally:
//first line of test
assumeThat(Boolean.parseBoolean(System.getProperty("deep.test.run","false"),true)
Doing this with gradle required that the system property provided at the time of running gradle build, shown here,
gradle build -Ddeep.test.run=true
was indeed passed through to the tests.
Hope this helps others trying out this approach for running tests conditionally.

Resources