renaming project names is not working - gradle

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

Related

Get rootPoject.name, or reference to settings.gradle, of included builds

I'm using includeBuild to include modules from my own library in settings.gradle:
rootProject.name = "MyApp"
include ':app'
includeBuild '/usr/local/library/Android/Event'
includeBuild '/usr/local/library/Android/Location'
includeBuild '/usr/local/library/Android/Widget'
I know I can iterate these later with:
gradle.includedBuilds.each{ includeBuild ->
println includeBuild.name
}
However, that prints:
Event
Location
Widget
Is there a simple way to get the rootProject.names that I have defined in each of those individual library projects' settings.gradle files?
I know I can do the following to give alternative names:
includeBuild('/usr/local/library/Android/Event', {name = 'com.example.android.event'})
includeBuild('/usr/local/library/Android/Location', {name = 'com.example.android.location'})
includeBuild('/usr/local/library/Android/Widget', {name = 'com.example.android.widget'})
... but that is redundant and cumbersome when I've already defined those as rootProject.name is their respective settings.gradle.
Rather, I'm looking for something akin to:
gradle.includedBuilds.each{ includeBuild ->
println includeBuild.rootProject.name
}
For instance, I know about includeBuild.projectDir. Can I somehow get a (parsed) reference to the settings.gradle file in that directory?
I've managed to solve it using org.gradle.tooling.GradleConnector:
import org.gradle.tooling.GradleConnector
import org.gradle.tooling.ProjectConnection
import org.gradle.tooling.model.GradleProject
def getIncludedProjectNamesMap(Project project) {
def projectNamesMap = new HashMap<String, String>()
project.gradle.includedBuilds.each { includedBuild ->
ProjectConnection connection = GradleConnector.newConnector()
.forProjectDirectory(includedBuild.projectDir)
.connect()
GradleProject includedProject = connection.getModel(GradleProject.class);
def name = includedProject.getName();
connection.close();
projectNamesMap.put includedBuild.name, name;
}
return projectNamesMap
}
println getIncludedProjectNamesMap(project)
... which prints:
{Event=com.example.android.event, Location=com.example.android.location, Widget=com.example.android.widget}
... but that appears to be rather slow, probably due to all the connections it need to make. It does the job for now, but I'm still looking for alternative approaches, if available.

Gradle processResources expand on different projects modules

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)

In the settings.gradle file how can i dynamically include all the subprojects?

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
}
}

Gradle copy and filter task not executed

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.

gradle tar include nested files at top level

In gradle (1.9), I have multiple subprojects. Each one uses the application plugin to create a tar and cli. I am trying to get all these tars into a unified tar, but I am having a lot of trouble.
Here is the tar format I am looking for:
${project.name}/${subproject.name}.tar
I have tried using both the Tar task and the distribution plugin, but for each one, I am not able to find a clean way to just get the generated tars (or any tar), and put them at top level, excluding everything else.
Here is a sample using the distirbution pluging, but its not giving the output I like
apply plugin: 'distribution'
distributions {
testing {
contents {
from(".")
exclude "*src*"
exclude "*idea*"
exclude "*.jar"
exclude ".MF"
filesMatching("**/build/distributions/*.tar") {
if(file.name == "${project.name}-testing.tar") {
exclude()
} else {
name file.name
}
}
}
}
}
Here is what I would like (but not working):
apply plugin: 'distribution'
distributions {
testing {
contents {
include "**/*.tar" // shows up at top level
}
}
}
EDIT:
Getting closer.
distributions {
testing {
contents {
from subprojects.buildDir
includeEmptyDirs false
include "**/*.tar"
exclude "**/${project.name}-testing.tar"
}
}
}
This will give me ${project.name}/distribution/${subproject.name}.tar
Here is the solution for your problem. Put the following to the root project:
task distTar(type: Tar) {
destinationDir = new File("$buildDir/distributions")
baseName = 'unifiedTar'
}
subprojects {
// definitions common to subprojects...
afterEvaluate {
def distTar = tasks.findByName('distTar')
if(distTar) {
rootProject.distTar.dependsOn distTar
rootProject.distTar.inputs.file distTar.archivePath
rootProject.distTar.from distTar.archivePath
}
}
}
then invoke "build distTar" on the root project - it will assemble "unifiedTar.tar" in "build/distributions" subfolder (of the root project).
How it works:
"task distTar(...)" declares a new task of type Tar in the root project.
"subprojects" applies the specified closure to each subproject.
"afterEvaluate" ensures that the specified closure is called AFTER the current project (in this case subproject) is evaluated. This is very important, because we are going to use properties of the subproject which are defined only after it's evaluation.
"tasks.findByName" allows us to determine, whether the given task is defined for given project. If not, it returns null and the following code is not performed. This way we stay agnostic regarding the nature of the subproject.
"dependsOn" ensures that distTar of the root project depends on distTar of the given project (and, therefore, is executed later than it).
"inputs.file" ensures that distTar on root project is not executed, if none of the constituent tars has changed.
"from" adds constituent tar to unified tar.

Resources