2. Gradle bootstraps your build extensions
If you put some code in a project named buildSrc, directly under the
root of your build, Gradle will automatically compile them and add them
to the classpath of the main build.
This allows you to quickly hack plugins, tasks or utility classes that you
use in your build scripts.
https://docs.gradle.org/current/userguide/organizing_build_logic.html#sec:build_sources
3. You can put all the code for your plugin in one file
class MyPlug implements Plugin<Project> {
void apply(Project project) {
def plug = project.extensions.create('timer', MyPlugExtension, project)
def countClasses = project.task('countClasses', type: CountClassesTask) as CountClassesTask
countClasses.input = project.file(project.buildDir, 'classes')
}
}
class MyPlugExtension {
Project project
void start() { project.ext.timestamp = System.currentTimeMillis() }
void end() { project.logger.lifecycle("Time elapsed ${System.currentTimeMillis() - project.timestamp}") }
}
class CountClassesTask extends DefaultTask {
@InputDirectory File input
@OutputFile File output
@TaskAction
void generateClassCountFile() {
def counter=0
def cfv = [visitFile: { file, attrs -> counter++ } ].withDefault { file, attrs -> } as FileVisitor
Files.walkFileTree(input.toPath(),cfv)
output.text = "$counter files"
}
}
Not necessarily a good idea, but I can and I often do
4. Use extensions to expose plugin level configuration
class MyPlug implements Plugin<Project> {
void apply(Project project) {
def plug = project.extensions.create('timer', MyPlugExtension, project)
def countClasses = project.task('countClasses', type: CountClassesTask) as CountClassesTask
countClasses.input = project.file(project.buildDir, 'classes')
}
}
class MyPlugExtension {
Project project
void start() { project.ext.timestamp = System.currentTimeMillis() }
void end() { project.logger.lifecycle("Time elapsed ${System.currentTimeMillis() - project.timestamp}") }
}
class CountClassesTask extends DefaultTask {
@InputDirectory File input
@OutputFile File output
@TaskAction
void generateClassCountFile() {
def counter=0
def cfv = [visitFile: { file, attrs -> counter++ } ].withDefault { file, attrs -> } as FileVisitor
Files.walkFileTree(input.toPath(),cfv)
output.text = "$counter files"
}
}
That means mostly settings.
Actually, you can put utility methods too,
but better keep them to config phase.
P.S. if you are not sure what the pre
paragraph means - just do settings.
5. Use tasks to do stuff
class MyPlug implements Plugin<Project> {
void apply(Project project) {
def plug = project.extensions.create('timer', MyPlugExtension, project)
def countClasses = project.task('countClasses', type: CountClassesTask) as CountClassesTask
countClasses.input = project.file(project.buildDir, 'classes')
}
}
class MyPlugExtension {
Project project
void start() { project.ext.timestamp = System.currentTimeMillis() }
void end() { project.logger.lifecycle("Time elapsed ${System.currentTimeMillis() - project.timestamp}") }
}
class CountClassesTask extends DefaultTask {
@InputDirectory File input
@OutputFile File output
@TaskAction
void generateClassCountFile() {
def counter=0
def cfv = [visitFile: { file, attrs -> counter++ } ].withDefault { file, attrs -> } as FileVisitor
Files.walkFileTree(input.toPath(),cfv)
output.text = "$counter files"
}
}
BTW, these strings are the names by
which the tasks and extensions would
appear in your build script when you apply
the plugin.
14. If you do this you can start debugging your builds!
gradlew -Dorg.gradle.debug=true --no-daemon build
● Attach remote debugger on port 5005
● Set breakpoints in your plugins and tasks under buildSrc
● Or Gradle classes that you see from the debug log
● You still cannot set breakpoints in the init scripts and build scritps.
One more reason to keep them declarative.
Keep in mind that Gradle decorates some objects such as tasks and extensions,