Gradle custom task type defined in buildSrc not accessible in subprojects for multi-project structure

I have a gradle multi-project hierarchy:

root
-buildSrc
    -src/main/groovy/com/CustomTask.groovy
-subproj1
-subproj1
-build.gradle
-settings.gradle

I am able to invoke custom task - com.CustomTask only from root build.gradle file but I get - Unable to resolve class CustomTask at line import com.CustomTask when called from subproj1/build.gradle

import com.CustomTask

task customTask(type: CustomTask) {
        setModuleRoot(project.projectDir)
    }

Can anyone please suggest me how can I invoke a custom task defined under root level buildSrc from subproject’s build.gradle file? (I am on gradle 7.1.1 version)

It should work just fine, can you provide an MCVE?

@Vampire posting here the outline:
The groovy custom task is defined under :
root/buildSrc/src/main/groovy/com/CustomTask.groovy

package com

import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction

abstract class CustomTask extends DefaultTask {

@TaskAction
void process() {
    ...
}

void setModuleRoot(File f) {

}

}

Note, i just provided an empty build.gradle file under /buildSrc so these are only 2 files under buildSrc

In root build.gradle

     ...
     import com.CustomTask
 
     task customTask(type: CustomTask) {
         setModuleRoot(project.projectDir)
     }
     ...

Similarly under subproject’s build.gradle same as above.

But running gradle builld fails for subproject’s build.gradle with - Unable to resolve class CustomTask at line import com.CustomTask and does not fail for root build.gradle

As I said, it should work just fine, can you provide an MCVE? Your outline especially misses on the C part.

@Vampire attached the zip file - gradle-proj-test.zip (83.5 KB) for complete gradle multi-project / MCVE as you suggested.

On running gradle customTask from root of project, can see this below error:

gradle-proj-test\subproj1\build.gradle’: 1: unable to resolve class com.CustomTask
@ line 1, column 1.
import com.CustomTask
^
1 error

If i comment this out, then the same code present in root build.gradle executes fine.

Please let me know is there anything I am missing or doing it wrongly.
Thanks for your time.!

That is not a multi-project build, but a composite build.
Those are three “independent” builds (and each should get its own settings script) that you combine as composite build using includeBuild in the settings script.
Each of these projects is a potential multi-project build, if you use include in their settings script to add subprojects.
In subprojects of a multi-project build you could use the classes from the builds buildSrc project, but not in “sub-builds”.
You could instead not use buildSrc and instead an included build (that’s what I do always nowadays anyway) and includ that build into all of the three builds, or you can make it a multi-project build instead of a composite build.

Ok sorry my bad.! I’m new to gradle world, and I want to acheive this without major changes, as the project i shared was just an dummy, the actual project is huge. So going with this composite build itself, so by “include build” you mean can I move the task definition to say - customTask.gradle under project root and then have this included in subproj’s/sub dir.s build.gradle thats what you mean ?

@Vampire just tried with having another customTask.gradle with import and task defined as above, and in subproject/sub dir’s build.gradle did apply from: '../customTask.gradle' but it gives same error:

gradle-proj-test\customTask.gradle’.
startup failed:
script ‘C:\Users\XDSOUZA\Desktop\gradle-proj-test\customTask.gradle’: 1: unable to resolve class com.CustomTask
@ line 1, column 1.
import com.CustomTask
^

1 error

No, that’s applying a script plugin, that I would do in almost no cases.
I said instead having buildSrc you have another included build.
So rename buildSrc to anything else like build-logic, give it a proper settings script and the do includeBuild("path/to/build-logic") in every build you need its classes, additionally you need to declare a buildscript dependency on it, unless it actually is a plugin you use from that project.

1 Like

@Vampire Thanks for your suggestion and time, i am almost there with my final solution.
As you suggested, i moved from buildSrc to a groovy project called build-logic, and added includeBuild('../build-logic') in subproject1’s settings.gradle and in subproject’s1 build.gradle added buildscript dependency as below:

buildscript {
dependencies {
classpath files(‘…/build-logic/build/libs/build-logic.jar’)
}
}

And it’s working with only condition that project build-logic must be built first else libs won’t be generated.
Can you please suggest how can I overcome this.

I tried buildscript dependency as project('../:build-logic') but that didnt work - project not found.

Basically need buildscript dependency for a project which is part of includeBuild and at one level above in file system. Can you please help me out in this. Hopefully the last problem for this discussion. Thanks.!!

You should never depend on a jar directly, as then of course no information about how it is built is available.
Also, you cannot use project(...) notation, as that is for within a multi-project build not for depending on an included build in a composite build.
You declare a dependency on the actual coordinates the project would get when you publish it, so something like classpath 'yourgroup:build-logic'. You can leave out the version as it is replaced by the included build anyway.

@Vampire yes that solved the build compilation, but strangely the actual custom task groovy code is not getting executed at runtime.

import com.CustomTask
task customTask(type: CustomTask) {
setModuleRoot(project.projectDir)
}

If i run gradle customTask it shows executed successfully, but i dont see any logs in the custom task code logged, and mainly the custom task generates a file which isnt generated in out directory.

Any idea? Sorry to bother you again and again, but your suggestions are being helpful. Thank you :slight_smile:

Can you provide a new MCVE?

Ok, i am able to run it from inside subproj1, but when running from root gradle customTask it fails. Attached - gradle-proj-test.zip (83.5 KB)
I want it to run from root, so that this task gets executed for all subproj… other subproj’s will basically have empty task defined.

Also do includeBuild 'build-logic' in the root builds settings script and as first one, then it works.