Gradle- Copy Dependencies of Sub Projects into respective folder of Sub Projects - gradle

From root, I am basically trying to fetch the dependencies of each sub project and copy into a directory named dependency within each subproject
I have a root Project and in that build.gradle file i have a task like below:
task copyDependencies(type:Copy) {
nonTestProjects.each {
delete rootProject.project(it).file('dependencies')
from rootProject.project(it).configurations.runtime
intorootProject.project(it).file('dependencies/')
}
}
Inside the Sub Projects build.gradle, i have dependencies as below:
dependencies
{
implementation "com.google.protobuf:protobuf-java:$protobufVersion"
implementation "io.netty:netty:$nettyVersion"
implementation "xmlpull:xmlpull:$xmlPullVersion"
}
On running the task copydependencies from root, i am getting error as below:
Could not get unknown property 'runtime' for configuration container of type org.gradle.api.internal.artifacts.configurations.DefaultConfig
urationContainer.

You get the error Could not get unknown property 'runtime' for configuration container because when gradle configures your root project and tries to create the task copyDependencies, the subprojects have not yet been evaluated, so Gradle doesn't know about "runtime" configuration at this stage ( java plugin has not yet been applied to subprojects).
So one solution would be to wrap this task creation into a gradle.projectsEvaluated lifecycle hook:
gradle.projectsEvaluated {
task copyDependencies(type:Copy) {
// task definition ...
}
}
But then you will have other issues because you want to copy different sources to different destination directories (see How to copy to multiple destinations with Gradle copy task? for possible solution to this issue)
I think a better way would be to create different copyDependencies tasks, one per subproject , and create an "aggregator" task in root project which will depend on these subprojects's tasks:
// aggregator task at root project level
task copyDependencies
// create copydependencies task for each (non-test) subproject
gradle.projectsEvaluated {
nonTestProjects.each {
Project proj = project(it)
Task task = proj.task('copyDependencies', type: Copy) {
from proj.configurations.runtimeClasspath
into proj.file("dependencies")
doFirst {
file('dependencies').deleteDir()
}
}
copyDependencies.dependsOn task
}
}

Related

Use build.finalizedBy on each subproject with Gradle kotlin

I want to run a specific task after EVERY build of my subprojects. I can go into each of my subprojects build.gradle.kts file and add the following
tasks.build {
finalizedBy("afterbuildtask")
}
However, this should be possible to do in my root project build.gradle.kts file right? I tried it by doing the following:
subprojects {
this.tasks.findByName("build")?.dependsOn("afterbuildtask")
}
But nothing happens. How can I achieve this?
You can't programatically execute tasks from other tasks in newer versions of Gradle.
Instead, you are supposed to declare task dependencies and Gradle will ensure they get executed in the correct order. But I think it's not what you want
Alternatively, you could move your logic into the doLast block in the build task. eg:
build {
doLast {
println("Copying...")
copy {
from 'source'
into 'target'
include '*.war'
}
println("completed!")
}
}
good coding! ¯_(ツ)_/¯

Create a second installDist task?

During development I am using a standard-function installDist (from the application plugin) in build.gradle:
installDist{}
... but I now want to have another task which installs/distributes/deploys a "production" version to the production location, which also incorporates the version into the directory structure. I tried this:
task deployOperativeVersion( type: installDist ) {
destinationDir = file( "$productionDir/$version" )
}
Build failure output:
Build file '/home/mike/IdeaProjects/JavaFXExp2/Organiser/build.gradle' line: 98
* What went wrong:
A problem occurred evaluating root project 'Organiser'.
> class org.gradle.api.tasks.Sync_Decorated cannot be cast to class java.lang.Class
(org.gradle.api.tasks.Sync_Decorated is in unnamed module of loader org.gradle.
internal.classloader.VisitableURLClassLoader #aec6354; java.lang.Class is in module
java.base of loader 'bootstrap')
It appears that installDist is not a "type" as in Test.
How can I achieve this? Incidentally I would be really keen on having two separate tasks: to get installDist to run I've found that you only have to type ./gradlew inst ... with a task called deployXXX it would be sufficient to type ./gradlew depl.
I also tried this:
task deployOperativeVersion{
installDist{
destinationDir = file( "$operativeDir/$version" )
}
}
... which doesn't seem to have done anything. Nor this:
task deployOperativeVersion{
doFirst {
installDist {
destinationDir = file("$operativeDir/$version")
}
}
}
A bit later I thought I had indeed found the answer:
task deployOperativeVersion{
dependsOn installDist{ destinationDir=file("$productionDir/$version")
}
... but to my amazement (will I ever get to a reasonable understanding of Gradle before Hell freezes over?), including this actually appears to influence the "routine" installDist task: specifically, it stops the latter from operating normally, and means that even when I run installDist the deployment/distribution/installation still goes to productionDir/version, rather than the default location.
So then I wondered about two tasks both of which are dependent on installDist:
task deployOperativeVersion{
dependsOn installDist{ destinationDir=file("$productionDir/$version") }
}
task stdInstall{
dependsOn installDist{ destinationDir=file("build/install") }
}
... haha, no joy: I run one and it deploys OK. I then run the other... and get an error:
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':installDist'.
> The specified installation directory '/home/mike/IdeaProjects/JavaFXExp2/Organiser/build/install' is neither empty nor does it contain an installation for 'Organiser'.
If you really want to install to this directory, delete it and run the install task again.
Alternatively, choose a different installation directory.
... needless to say, this is NOT the case: under ...Organiser/build/install there is one directory only, Organiser, with /bin and /lib directories under it.
Your task should be declared as a Sync task, which is the actual type of the installDist task. The application plugin is using the distribution plugin. You can grab the content configuration from the main distribution, which is the source, or from the installDist task.
task deployOperativeVersion(type: Sync) {
destinationDir = file("${productionDir}/${version}")
with distributions.main.content
}
or
task deployOperativeVersion(type: Sync) {
destinationDir = file("${productionDir}/${version}")
with installDist
}

How to copy files between sub-projects in Gradle

How can I make a sub-project copy a file that is produced by a sibling sub-project? All this with proper dependency management, and without assuming that any language-specific plugins (like the JavaPlugin) are used.
I have looked at the updated Gradle 6 draft Sharing artifacts between projects but it does not really answer that question.
My multi-project structure is something like:
top/
build.gradle
settings.gradle
producer/
build.gradle
myFile_template.txt
consumer/
build.gradle
I want a Copy-task in producer/build.gradle to copy+transform myFile_template.txt into $buildDir/target/myFile.txt and another Copy-task in consumer/build.gradle should further copy+transform that myFile.txt to a finalFile.txt.
Presumably a proper solution would be able to use task outputs.files or some such so that consumer/build.gradle does not need to explicitly mention the location of $buildDir/target/myFile.txt.
(I'm completely new to Gradle).
Gradle gives you lots of freedom but I prefer that projects only "share" with each other by Configurations and/or Artifacts. I feel that one project should never concern itself with another project's tasks and feel that the tasks are private to each project.
With this principle in mind you could do something like
project(':producer') {
configurations {
transformed
}
task transformTemplate(type: Copy) {
from 'src/main/template'
into "$buildDir/transformed"
filter(...) // transformation goes here
}
dependencies {
// file collection derived from a task.
// Any task which uses this as a task input will depend on the transformTemplate task
transformed files(transformTemplate)
}
}
project(':consumer') {
configurations {
producerTransformed
}
dependencies {
producerTransformed project(path: ':producer', configuration: 'transformed')
}
task transformProducer(type:Copy) {
from configurations.producerTransformed // this will create a task dependency
into ...
filter ...
}
}

Can't define task dependencies between multiple projects using gradle

I need to build 2 projects using Gradle.
I have the 2 gradle files for each project and a parent gradle file.
In the settings.gradle I define the projects:
include 'loadRemote'
include 'load'
rootProject.name = 'EquipLoad'
project(':loadRemote').buildFileName = 'buildRemote.gradle'
project(':load').buildFileName = 'buildLoad.gradle'
Each of the subprojects has their own defined compile and stage tasks.
I need the loadRemote project to run first then the load project.
How to I create this dependency?
I tried adding the dependency to the build.gradle file like this:
tasks.getByPath(":load:cleanCompileStage").dependsOn(":loadRemote:cleanCompileStage")
But the load project compiles first.
I found these syntax:
project(':load') {
dependencies {
compile project (':remoteLoad')
}
}
But need to replace the Gradle compile task with the one that I created in the subproject. I am not sure if it is allowed.
Does anyone have any ideas how to define the dependencies of tasks between 2 subprojects?
You can modify your script like this:
project(':load') {
war.dependsOn project(":loadRemote").tasks.compileJava
}
The above answer did not work for me. I'm sure it is unique to my project. I have to create 2 ear files using 1 code base.
What I did was create a parent gradle file, build.gradle, and add tasks in there that used both projects like this:
//This task builds load and loadRemote ear using 1 command, buildAll
gradle.projectsEvaluated {
task compileAll (dependsOn: [project(':loadRemote').remoteLoadCleanCompileStage]) {
compileAll.finalizedBy project(':load').loadCleanCompileStage
}
task packageAll (dependsOn: [project(':loadRemote').remoteLoadPackage]) {
packageAll.finalizedBy project(':load').loadPackage
}
task buildAll (dependsOn: [compileAll]) {
buildAll.finalizedBy packageAll
}
}

Gradle task can be defined in root but not in child

I have a gradle sync task:
task updateSharedCode {
group = 'build'
}
updateSharedCode << {
sync {
from '../employee_shared/src'
into 'src/shared'
}
}
If I paste this task in the root's subprojects object everything runs fine But I only want to run this on a small subsection of my subprojects. But when I copy this task into one of the subprojects and remove it from the root I get the error
Execution failed for task ':employee_app:updateSharedCode'.
Could not find method from() for arguments [../employee_shared/src] on project ':employee_app'.
I have no clue why this is happening so any help would be helpfull.

Resources