i'm trying to get a project.version so i wrote project2 gradle before codes
processResources {
def props = ['version': project.properties.get('version')]
filesMatching("**/MyConfiguration.kt") {
expand(props)
}
}
the MyConfiguration.kt file located project1 but the code return null
so i fixed codes like below
processResources {
def props = ['version': project.properties.get('version')]
expand(props)
}
then that codes return right value
maybe the problem is filesMatching input another module file?
i missed filesMatching input
need to setup .properties or .yaml (get project.properties this scope)
Related
As settings.gradle file runs on groovy is it possible to write a script which will include all the subprojects which contains for example build.gradle files inside it.
I tried using this
new File('.').eachFileRecurse {
if (it.name.endsWith("build.gradle")) {
//include it
println "Processing file ${it}"
}
}
but can't figure out how it will work. I mean how will i include all my subprojects
I don't want to hardcode include 'x', include 'y' in the settings.gradle file
You can call include with the parent of the locations where the
build.gradle files are found. Be careful to not include things
multiple times or the root itself by the net you are casting.
E.g.
new File('.').eachFileRecurse {
if (it.name == "build.gradle" /* && ... more checks */)) {
println "Included directory ${it.name} due to ${it}"
include it.parent
}
}
How do I access the value of an argument from the command line in a gradle task? I know that this can be done by -P but I have the same property in my properties file and gradle picks the argument from the properties file rather than the command line. How do I prioritize accepting arguments from the command line over the properties file?
build.gradle
Properties props = new Properties()
props.load(new FileInputStream("./local.properties"))
props.each { prop ->
project.ext.set(prop.key, prop.value)
}
task print {
println("Gets = ${remote}");
}
local.properties
remote=from_properties
Command from cmd
gradle print -Premote=from_commandline
Output
Gets = from_properties
You shouldn't use your own local.properties file if you intend to use a properties file for Gradle properties.
Just use gradle.properties instead.
Also notice that you shouldn't declare task code inside its configuration block, you need to use doFirst or doLast:
gradle.properties
remote = properties
build.gradle
task print {
doLast { println "Gets = ${remote}" }
}
If you run ./gradlew print you will see Gets = properties.
If you run ./gradlew print -Premote=foo you should see Gets = foo.
That said.... if you really want your own properties file, you need to implement the order of priority yourself, Gradle cannot guess what you prefer.
For example, you could check if a property is already set before setting it:
def props = new Properties()
props.load(new FileInputStream("./local.properties"))
props.each { key, value ->
if (!project.hasProperty(key)) {
project.ext.set(key, value)
}
}
In a gradle project, I'm trying to change properties file value before generating WAR in build.gradle as follows,
war {
doFirst {
def propertyFile = file "src/main/resources/properties/about/About.properties"
def props = new Properties()
propertyFile.withReader { props.load(it) }
props.setProperty('releaseDate', new Date().format("yyyy-MM-dd HH:mm:ss"))
propertyFile.withWriter { props.store(it, null) }
}
rootSpec.exclude("**/test.jar")
}
But whenever I give build, it generates WAR with previous date time. Say, I'm giving first build at 11:30 and second build at 11:34. The second built WAR contains time as 11:30 instead of 11:34. My intention is to update date whenever WAR is built. Is this way right?
I simplified your solution and tested it. For me it always updates the date in the properties file when i run build or just war. Be aware that i changed the path for test purposes. Here is the code:
war {
doFirst {
File propsFile = file "src/main/resources/about.properties"
Properties props = new Properties()
props.load(propsFile.newDataInputStream())
props.setProperty('releaseDate', new Date().format('yyyy-MM-dd HH:mm:ss'))
props.store(propsFile.newWriter(), null)
}
}
Keep in mind that the releaseDate of the about.properties is not included into the current war you are currently building since resources for the war you are packing had been processed before you execute war.
If you want to include the about.properties file with the time of the current build into the war archive, you should create a custom task to update your properties file and hook the task to a point into the buildchain before resources are processed. I created a sample task for you:
task updateReleaseDate {
doLast {
File propsFile = file "src/main/resources/about.properties"
Properties props = new Properties()
props.load(propsFile.newDataInputStream())
props.setProperty('releaseDate', new Date().format('yyyy-MM-dd HH:mm:ss'))
props.store(propsFile.newWriter(), null)
}
}
processResources.dependsOn updateReleaseDate
Without the custom task your buildchain looks like this. The properties are updated after the resources are processed by the processResources task and therefore not included in the current war: compileJava->processResources->classes->war
With the custom task your buildchain looks like this. The properties are updated before the resources are processed by the processResources task and therefore included in the current war: compileJava->updateReleaseDate->processResources->classes->war
We are filtering an xml file replacing some tokens with gradle properties.
But the filtering (i.e. copy task) is not executed when we just change the properties in our build.gradle file.
How should we modify our script so that the filtering is performed each time or at least when the template and/or the build.gradle has been modified.
This we have:
war.doFirst {
delete 'src/main/webapp/WEB-INF/appengine-web.xml'
copy {
from 'build.gradle'
from 'src/main/webapp/WEB-INF/'
into 'src/main/webapp/WEB-INF/'
include '*-template.*'
rename { String fileName ->
fileName.replace('-template', '')
}
expand(gaeApp: "$gaeApp", gaeAppVersion: "$gaeAppVersion")
}
}
I just ran some test where the filtering worked. I am confused... I am sure that it sometimes does not!
So after good input from Vampire we tried this
war {
inputs.file "build.gradle"
exclude 'src/main/webapp/WEB-INF/appengine-web.xml'
// filesMatching('src/main/webapp/WEB-INF/**/*-template.*') {
filesMatching('**/*-template.*') {
println "WAR template: $it"
rename { it.replace '-template', '' }
expand gaeApp: gaeApp, gaeAppVersion: gaeAppVersion
}
}
A dollar and a dime to anyone who can explain why the filesMatching('src/main/webapp/WEB-INF/**/*-template.*')does not work!
BUT the biggest problem is that even if the filesMatching locates the template file the appengine-web.xml that is placed inside the WAR is not a processed version of appengine-web-template.xml.
You need to add those properties to the inputs of the task like
war.inputs.property 'gaeApp', gaeApp
war.inputs.property 'gaeAppVersion', gaeAppVersion
so that gradle knows the input changed, otherwise it cannot know when the input is different.
But besides that, you should not (need not) use a copy { } block in there.
The war task itself is an implicit copy spec, so you should be able just doing something like
war {
inputs.property 'gaeApp', gaeApp
inputs.property 'gaeAppVersion', gaeAppVersion
exclude 'src/main/webapp/WEB-INF/appengine-web.xml'
filesMatching('src/main/webapp/WEB-INF/**/*-template.*') {
rename { it.replace '-template', '' }
expand gaeApp: gaeApp, gaeAppVersion: gaeAppVersion
}
}
This is what worked for us in the end.
We moved the template to 'src/template/webapp' and removed the "-template" suffix,
war {
inputs.file "build.gradle"
with copySpec {
from 'src/template/webapp'
expand gaeApp: gaeApp, gaeAppVersion: gaeAppVersion
}
}
Our problem with Vampire's solution must be related to the fact that the template file was in same directory as the file it was to replace.
In my settings.gradle file, I originally had this which works
include 'server', 'webapp'
I modify it to this and it breaks
include 'server', 'webapp'
modifyProjectNames(rootProject, "sdi-")
def modifyProjectNames(project, prefix) {
project.children.each {
it.name = prefix + it.name
}
}
It says "project with path ':webapp' could not be found in root project 'SDI'" so I modify my file to this instead
include 'master', 'sdi-webapp'
modifyProjectNames(rootProject, "sdi-")
def modifyProjectNames(project, prefix) {
project.children.each {
it.name = prefix + it.name
}
}
I get the same exact failure yet I have no :webapp in settings.gradle so it must be my main gradle build file so I rename that project now as well to :sdi-webapp so now the error changes slightly to
Project with path ':sdi-webapp' could not be found in root project 'SDI'.
I have a project structure like so
SDI
- server
- webapp
and I want all the project names to be sdi-server and sdi-webapp, etc. etc. BUT I want the directories to be called
/SDI/server instead of /SDI/sdiserver
/SDI/webapp instead of /SDI/sdiwebapp
ie. no sense in being redundant there.
EDIT
I tried the first answer on another project like so
include 'master', 'toneserver','webserver'
modifyProjectNames(rootProject, "sdi-")
def modifyProjectNames(project, prefix) {
project.children.each {
it.name = prefix + it.name
}
}
rootProject.children.each {proj ->
proj.projectDir = file(proj.name - "sdi-")
}
It simply failed with
Project with path ':toneserver' could not be found in root project 'stserver'
It kind of works if you go through your build.gradle file and modify EVERY reference to also have the prefix which kind of defeats that programming rule of trying not to repeat yourself :( :( so if I ever want to modify the prefix, I have to do an ugly find and replace :(...ick. but it does work.
thanks,
Dean
as a workaround, you ca try to use the projectnames you prefere (SDI-...) in your include calls and change the projectDir of each subproject:
rootproject.children.each{proj->
proj.projectDir = file(proj.name - "SDI-")
}
cheers,
rene