Slackbot
09/21/2022, 1:47 PMEric Haag
09/21/2022, 2:10 PMdoLast
you instead use project.property("greeting.message")
to retrieve your property?Alon Eitan
09/21/2022, 2:17 PMgreeting.message
in the extension block:
greeting {
message="greeting1"
}
then it results in an error:
* What went wrong:
Execution failed for task ':greetingTask'.
> Could not get unknown property 'greeting.message' for root project 'proj1' of type org.gradle.api.Project.
Jendrik Johannes
09/21/2022, 2:17 PMproject.getProviders().gradleProperty("greetings.message")
You then have to pass that to your extension. For example instead of getMessage().convention("greeting0")
above, you could do getMessage().convention(project.getProviders().gradleProperty("greetings.message"))
This is a common problem/pattern. That’s why @benedikt and I have created a plugin that basically generates this setup for you. Maybe it fits your use case: https://github.com/gradlex-org/build-parametersAlon Eitan
09/21/2022, 2:19 PMGreetingPluginExtension
class to have access to the project
instanceJendrik Johannes
09/21/2022, 2:21 PMgreeting.getMessage().convention(project.getProviders().gradleProperty("greetings.message"))
right after you created the extension.Jendrik Johannes
09/21/2022, 2:22 PMProject project
as parameter to the constructor and add @Inject
to the constructor.Jendrik Johannes
09/21/2022, 2:22 PMinterface
without a constructor.Alon Eitan
09/21/2022, 2:23 PMAlon Eitan
09/21/2022, 2:23 PMAlon Eitan
09/21/2022, 2:25 PM* What went wrong:
A problem was found with the configuration of task ':greetingTask' (type 'GreetingTask').
- In plugin 'extension_example.greeting' type 'extension_example.GreetingTask' property 'message' doesn't have a configured value.
Reason: This property isn't marked as optional and no value has been configured.
Possible solutions:
1. Assign a value to 'message'.
2. Mark property 'message' as optional.
Please refer to <https://docs.gradle.org/7.5.1/userguide/validation_problems.html#value_not_set> for more details about this problem.
Jendrik Johannes
09/21/2022, 2:27 PM-P
, right? You should be able to chain another convention:
greeting.getMessage().convention(project.getProviders().gradleProperty("greetings.message").convention("defaultMessage"))
Jendrik Johannes
09/21/2022, 2:27 PMbuild
it, the code generated by the “build-parameters” plugin should follow this pattern. You can find that in build/generated-src
Alon Eitan
09/21/2022, 2:28 PMAlon Eitan
09/21/2022, 2:32 PMconvention
chaining works in providing a default value, but it doesn't identify it when I add -Pgreeting.message="greeting2"
to the command lineAlon Eitan
09/21/2022, 2:33 PMgreeting
and greetings
with the extra sJendrik Johannes
09/21/2022, 2:33 PMs
when I gave the samples. 😄Jendrik Johannes
09/21/2022, 2:34 PMAlon Eitan
09/21/2022, 2:34 PMAlon Eitan
09/21/2022, 2:34 PMJendrik Johannes
09/21/2022, 2:35 PMEric Haag
09/21/2022, 2:35 PMgreeting.getMessage().convention(project.getProviders().gradleProperty("greetings.message")
means the value of the extension property will take priority over the command line parameter, correct? Generally you want it to be the other way around where the command line parameter takes priority, right?Alon Eitan
09/21/2022, 2:36 PMAlon Eitan
09/21/2022, 2:38 PM// GreetingsPlugin.java
package extension_example;
import org.gradle.api.Project;
import org.gradle.api.Plugin;
import org.gradle.api.provider.Property;
import javax.inject.Inject;
abstract class GreetingPluginExtension {
abstract Property<String> getMessage();
@Inject
public GreetingPluginExtension(Project project) {
getMessage().convention(project.getProviders().gradleProperty("greeting.message")).convention("greeting0");
}
}
public class GreetingsPlugin implements Plugin<Project> {
public void apply(Project project) {
GreetingPluginExtension extension = project.getExtensions().create("greeting", GreetingPluginExtension.class);
project.getTasks().register("greetingTask", task -> {
System.out.println(extension.getMessage().get());
});
}
}
// build.gradle
plugins {
id 'extension_example.greeting' version 'unspecified'
}
repositories {
mavenLocal()
}
greeting {
message = 'greeting1'
}
Alon Eitan
09/21/2022, 2:39 PMgreeing{}
block and run gradle greetingTask -Pgreeting.message="greeting2"
I get
> Task :greetingTask
greeting0
Jendrik Johannes
09/21/2022, 2:39 PMconvention
is in the wrong place so that it overrides the first one:
This
...gradleProperty("greeting.message")).convention("greeting0")
should be
...gradleProperty("greeting.message").convention("greeting0"))
Alon Eitan
09/21/2022, 2:42 PMgetMessage().convention(project.getProviders().gradleProperty("greeting.message").convention("greeting0"));
Alon Eitan
09/21/2022, 2:42 PMerror: cannot find symbol
getMessage().convention(project.getProviders().gradleProperty("greeting.message").convention("greeting0"));
^
symbol: method convention(java.lang.String)
location: interface org.gradle.api.provider.Provider<java.lang.String>
Jendrik Johannes
09/21/2022, 2:43 PMAlon Eitan
09/21/2022, 2:43 PMEric Haag
09/21/2022, 2:45 PMString message = project.getProviders().gradleProperty("greeting.message").getOrElse(extension.getMessage().get())
Alon Eitan
09/21/2022, 2:47 PMAlon Eitan
09/21/2022, 2:48 PMgetMessage().convention(project.getProviders().gradleProperty("greeting.message").orElse("message0"));
this works, however it treats the value in the greeting {}
block with MORE precedence over the command lineEric Haag
09/21/2022, 2:48 PMJendrik Johannes
09/21/2022, 2:49 PMJendrik Johannes
09/21/2022, 2:49 PMAlon Eitan
09/21/2022, 2:49 PMJendrik Johannes
09/21/2022, 2:50 PMAlon Eitan
09/21/2022, 2:50 PMAlon Eitan
09/21/2022, 2:50 PMJendrik Johannes
09/21/2022, 2:50 PMmessage
as a task input later, you have to check. Because accessing properties directly from within the task is bypassing declaring them as inputs correctly.Alon Eitan
09/21/2022, 2:51 PM@Input
now and see if that worksEric Haag
09/21/2022, 2:51 PMJendrik Johannes
09/21/2022, 2:52 PMJendrik Johannes
09/21/2022, 2:53 PMAlon Eitan
09/21/2022, 2:55 PMJendrik Johannes
09/21/2022, 2:55 PM.convention("greeting0")
and then not change it in another place in the build again. Then the -P
value wins over the value you set there. And that’s more or less what the plugin is also doing. Only that the code the plugin generates actually prevents you from changing the value (it’s using Providers instead of Properties).Jendrik Johannes
09/21/2022, 2:56 PM-P
and you can define a default value.
You can not change things in the extension block (the extension is read-only you could say)Alon Eitan
09/21/2022, 2:58 PMAlon Eitan
09/21/2022, 2:58 PMJendrik Johannes
09/21/2022, 3:00 PMAlon Eitan
09/21/2022, 3:00 PMAlon Eitan
09/21/2022, 3:01 PMJendrik Johannes
09/21/2022, 3:01 PMJendrik Johannes
09/21/2022, 3:01 PMAlon Eitan
09/21/2022, 3:01 PMAlon Eitan
09/21/2022, 3:02 PMAlon Eitan
09/21/2022, 3:02 PMJendrik Johannes
09/21/2022, 3:03 PMAlon Eitan
09/21/2022, 3:03 PMJendrik Johannes
09/21/2022, 3:04 PMAlon Eitan
09/21/2022, 3:04 PMAlon Eitan
09/21/2022, 3:04 PMAlon Eitan
09/21/2022, 3:04 PMAlon Eitan
09/21/2022, 3:06 PMgradle.properties
file
5. Gradle properties defined in project's gradle.properties
file
6. Gradle properties defined in gradle installation directory gradle.properties
file
7. Project properties defined in ext {}
block
8. Project properties defined in extension blocksAlon Eitan
09/21/2022, 3:06 PMJendrik Johannes
09/21/2022, 3:08 PMgetMessage().convention("greeting0")
• But for the task you then involve the greeting.message
property getMessageTaskInput().set(project.getProviders().gradleProperty("greeting.message")).convention(extension.getMessage())
It’s similar to what Eric proposed, only that you do it on the task inputs and not inside the task action.Jendrik Johannes
09/21/2022, 3:10 PMthe numerous ways to define propertiesYes. That’s why I would avoid using them if you can. 😄 In the context of the build parameters plugin, we basically said that we want to support
-P
. The other things automatically work as well, but we do not encourage using them.Jendrik Johannes
09/21/2022, 3:11 PMJendrik Johannes
09/21/2022, 3:11 PM-P
as we have discussed here.Alon Eitan
09/21/2022, 3:12 PMJendrik Johannes
09/21/2022, 3:13 PMproject.getProviders().gradleProperty("greeting.message")
all the ways to define properties from the outside still work (-P, gradle.properties, …)Alon Eitan
09/21/2022, 3:14 PMAlon Eitan
09/21/2022, 3:14 PMJendrik Johannes
09/21/2022, 3:15 PMAlon Eitan
09/21/2022, 3:15 PMVampire
09/21/2022, 10:53 PMgradle.properties
), you could also consider using @Option
properties on your tasks.Alon Eitan
09/22/2022, 10:45 AMgradleProperty
method returns a Provider<String>
, so the code we wrote above only works for String
propertiesAlon Eitan
09/22/2022, 10:45 AMVampire
09/22/2022, 11:35 AM.map
it to the type you want to haveJendrik Johannes
09/22/2022, 11:35 AMgradleProperty("abc").map { it.toInt() }
Matan Sabag
09/23/2022, 6:15 PM