I am writing a plugin for Gradle. I spent a lot of time and do not know how to solve the problem correctly.
I need automatically run build task before running my own task. DependsOn is not suitable as it tightly binds tasks, and I want to take advantage of Gradle's input, output principle. What commonly can be triggered in project as input paramether for my task for such behaviours?.
gradle customTask
result:
:build
+----:customTask
My castomTask uses project.configuration() and I try mark it as #InputFile but it dosent trigger build task.
Related
I am specifically looking to see if you can create a task that depends on the internal "assembleRelease" gradle task in a multi-project environment. There are many, many independent pieces that need building here, so changing in all of the build files is not optimal.
My basic situation is looking for a task, for example "release" that can call :a:assembleRelease, :b:assembleRelease and :c:assembleRelease without having to type in the names of all of the projects to begin with.
I have attempted the following task definition in the root project build.gradle.kts:
tasks.register("release") {
finalizedBy(tasks.getByPath("assembleRelease"))
}
as well as tasks.getByName, and trying to go through the gradle taskGraph. The task graph doesn't appear to be the right path at all, but I'm not sure if this is a possible task or is against the conventions of gradle to do things this way.
You would just define a task that depends on multiple other tasks.
Assuming the root project:
tasks {
register("release") {
dependsOn(
named(":a:assembleRelease"),
named(":b:assembleRelease:),
named(":c:assembleRelease")
)
}
}
You can add essentially an infinite amount of task dependencies. See Authoring Tasks for more details, specifically Adding dependencies to a task.
I am trying to reduce the time taken to run tests using gradle. Since there are multiple projects, one of the ways that I can think of doing that is to split tests into Unit and Integration tests. For each project, I have created two different tasks: unitTests task and integrationTests task.
Assume for simplification, that we always run gradle build -x test before running tests. In such a scenario, I am trying to get to state where I can run the tasks unitTests and integrationTests in parallel.
Currently I have seen failures where one of the tasks starts compiling the project leading to the other task failing with the error : "Cannot read zip file" which is likely because the JAR that the project depends on is now being updated by the other process. This seems to be likely because we have compileJava and compileTestJava as dependent tasks which interfere with dependent projects leading to a failure.
Wondering if there is a way in gradle to do the following :
Run only tests and not compile anything (to the tune of surefire:test in maven).
If not, is there settings that can be specified in build.gradle to tell gradle not to modify files but just to run tests.
Gradle does not (yet) support running multiple tasks of the same project in parallel. However when running tests, these can be run in parallel inside a given test task.
For your issues of having errors potentially due to files being changed while other things run, make sure Gradle knows about all the dependencies between tasks as it will be the best way of solving these problems.
As for work avoidance, Gradle is optimised to only do the minimum required, including tasks up to date checks, compilation avoidance and more. So invoking test will only compile code if there were changes since last execution.
I have a pretty large git project that I have a large single build.gradle that defines the sub projects.. For the first few years... no problem. After the first few years it gets kind of slow on the Gradle Command line configuration step because of the number of sub projects.
For example, when I run a gradle command I see a pause on:
> Configuring > 0/77 projects > ...
The pause gets bigger with each project added it seems like.
Another big problem is when i go to import the project or refresh the gradle deps with intelliJ, it takes a long time on the "analyzing dependencies" really delaying development as we need to have a pretty large wait everytime we sync dependencies.
What do people do in the field typically to get passed this? I have had to just eat the delay which is painful.
Do people usually split up the build.gradle file into unrelated chunks so that you get a network of multi-project builds? Or should there be a way to make that not be so damn slow?
I have analyzed the dependencies, all pretty simple actually.
Ondemand, Daemon and, parallel deploys happen in some limited way.
But the same problem stands...
What other tricks are out there? My plan is to separate the main parts of my code in sections and load them independently so that the gradle commands and intelliJ refreshes are smaller UP-TO-DATE check and configuration setup. It would be nice if we didn't have to split up our build.gradle file just because of sub-project limit.
Following our discussion in the comments of your question, it is fairly clear that you don't want to go down the route of publishing some of the interface jars to a repository to remove some of the subprojects.
Given that, here are a few suggestions. I know you have already tried some of them, but there are a few here that you haven't mentioned above which might help you slightly:
Profiling and dry run
First of all, try using the following command:
./gradlew {task} --dry-run --profile
This will perform a dry run of the task with name {task} and create a profile html file under $buildDir/reports/profile. You can use this to see which tasks are taking up the majority of the time across congifuration, dependency resolution and task execution. If you can see that one task is taking a particularly long time, have a look at it and see if you can cut down what is happening in that task.
Configuration on demand
To reduce configuration time, try enabling configuration on demand in your gradle.properties file like so:
org.gradle.configureondemand=true
This will mean that instead of configuring everything, gradle will attempt to only configure the necessary projects required to run a task.
Use the gradle daemon
The gradle daemon is a background process which doesn't exit when your gradle task finishes, and can be reused. This limits the amount of overhead of starting a new gradle jvm process every build. To activate the gradle daemon, add the following line to your gradle.properties file:
org.gradle.daemon=true
Use the most recent possible versions of Gradle and Java
Something is simple as upgrading your gradle version can improve speed. If you haven't upgraded for a while, or are using a fairly old version, consider upgrading. There may be some initial pain in upgrading, but it will be worth it in the long run. The same applies for upgrading java versions. Obviously, this is not always possible due to other constraints, but try and use the most recent java version available to you.
Avoid using dynamic dependencies
Gradle allows your to specify ranges for dependencies that your project is able to use like so:
dependencies {
compile "commons-lang:commons-lang:2.+"
}
This means that gradle will always try and find the latest version of the dependency that matches the constraint. This flexibility comes at a performance cost as gradle will have to go online to check what version to use. For this reason, and a few others that I won't go into here, it is a good idea to specify the version of a dependency explicitly.
Parallelize the build
This allows unrelated subprojects to be built in parallel, which speeds up the build process. To enable this, set the following in gradle.properties:
org.gradle.parallel=true
Ignore non-relevant tasks
Say you want to do a build, but don't necessarily want to run all of the tests again. You can run the following task, and the test task will not be run. This can significantly increase build time:
./gradlew build -x test
EDIT -- Following some further research, and after finding this answer, I had further suggestions.
Disable parts of the build using properties
As shown in the linked question, if you have a project and you only want to run the functional tests under certain circumstances, you can add the following to the root build.gradle file:
project('functional-tests') {
test {
onlyIf {
project.hasProperty("functionalTests")
}
}
}
This means that functional tests will only be run if you run a task like so:
./gradlew test -PfunctionalTests
Disable certain subprojects in the settings.gradle
You could also disable certain subprojects in the settings.gradle like so:
if (someBoolean) {
include 'functional-tests'
}
How to edit those Gradle tasks or create my new Gradle tasks. I have googled but cannot find enough information.
These are Gradle Tasks, I want to create here new Gradle Tasks or is there any way I can edit (change code) and see code of these tasks?
I have a problem in organizing my build in manageable way. In my gradle build there are large number of tasks since for each specific work element, gradle require a task of that type. For ex: to copy a file gradle needs Copy task type, and to zip a file gradle needs Zip task type, to delete few files gradle needs Delete task type. Javadoc , Jar , Ear etc also require their task types. Eventually build has large number of tasks and to run all these in specific order I have to use
taskA.mustRunAfter taskB
Applying these rules to for all the tasks make build more unmanageable. Is there a way to program all those work elements ( i.e, copy files, zip files, create a jar and javadoc, etc ) in one task ( like provided in ant )
Is there a reason you aren't using dependsOn? You'll need to specify a lot more mustRunAfter statements to achieve the same ordering that dependsOn can get you. At least, that's my experience. Only use mustRunAfter when you have an ordering issue that explicitly is not a dependency.
For example, we use gradle to install and uninstall testing environments. If both are run than install.mustRunAfter uninstall (to do a refresh) but clearly install doesn't always actually depend on uninstall so we use mustRunAfter.
That said, one way you can run many elements in one task is to use a series of ant goals.
task lotsOfStuffAtOnce {
ext.paulaProp = 'brillant'
} << {
ant.copy ...
ant.zip ...
ant.jar ...
}
I still think that overall the preferred philosophy is to use tasks with a proper mix of dependsOn and mustRunAfter, but different situations call for different results so who am I to judge? If you're looking to accomplish several steps all as one unit of work (one task) the above code is the cleanest way I can think of doing it.
If you don't have experience calling ant from gradle, the user docs will show you that it's a pretty mechanical transformation.