-
-
Save johnrengelman/9a20697b2246a9bfaca2 to your computer and use it in GitHub Desktop.
| //place this content in your buildSrc/build.gradle file | |
| //Then apply your plugin to its own build in build.gradle | |
| import org.codehaus.groovy.control.CompilerConfiguration | |
| apply plugin: 'groovy' | |
| repositories { | |
| jcenter() | |
| } | |
| // IntelliJ doesn't let you set the source path for a module outside of its directory. | |
| // This logic basically only performs this configuration when not being resolved in IntelliJ | |
| if (!project.plugins.collect { it.class.name}.any { it.endsWith('JetGradlePlugin')}) { | |
| //Set the source directories for buildSrc to contain the source from the main project | |
| sourceSets { | |
| main { | |
| java.srcDirs = ['src/main/java', '../src/main/java'] | |
| groovy.srcDirs = ['src/main/groovy', '../src/main/groovy'] | |
| resources.srcDirs = ['src/main/resources', '../src/main/resources'] | |
| } | |
| } | |
| } | |
| // Prepare to have your mind blown | |
| // This section evaluates the `build.gradle` from the root diretory and | |
| // then grabs the dependencies block from it and evaluates it on this project. | |
| // So in effect, we are building the main project with itself. | |
| // BOOM | |
| ScriptHolder holder = new ScriptHolder() | |
| CompilerConfiguration cc = new CompilerConfiguration() | |
| cc.setScriptBaseClass(DelegatingScript.class.name) | |
| GroovyShell sh = new GroovyShell(Project.class.classLoader, new Binding(), cc) | |
| //The build file for the main project | |
| File projectBuildFile = file('../build.gradle') | |
| //Use this parse command because Groovy wants to use the file name as the classname | |
| //which fails if your Gradle build file has been renamed to contain an invalid character (i.e. '-') | |
| DelegatingScript script = (DelegatingScript)sh.parse(projectBuildFile.text, 'GradlePlugins') | |
| script.setDelegate(holder) | |
| //Resolve the project main Gradle file against our ScriptHolder | |
| script.run() | |
| //Class for holding the evaluation of a Gradle script | |
| //You may need to add some extra methods here depending on what you have all placed in build.gradle | |
| class ScriptHolder { | |
| Closure dependencies | |
| void dependencies(Closure c) { | |
| this.dependencies = c | |
| } | |
| void apply(Map map) { | |
| } | |
| } | |
| //Grab the dependencies closure and resolve it against | |
| //the buildSrc project dependencies | |
| //This effectively applies the same dependenices from build.gradle into buildSrc/build.gradle | |
| //This is required so that when buildSrc is compiled it has the dependencies to compile the source code | |
| def closure = holder.dependencies.clone() | |
| closure.delegate = project.dependencies | |
| closure() |
@grv87 unless I'm missing something, you can't use buildSrc if you're also publishing your plugin. The method used by @ysb33r works, you just need to remember to add any dependencies to your buildscript dependencies (as classpath dependencies).
The script from @johnrengelman, OTOH, just didn't work for me. And it was far from clear why ...
@CliveEvans I also couldn't get @johnrengelman script to work for me, although its likely because of the version of Gradle I am running. This was my error:
No signature of method: GradlePlugins.buildscript() is applicable for argument types: (GradlePlugins$_run_closure1) values: [GradlePlugins$_run_closure1@2e7cad0f]
@wheelerlaw hard to know without the stack trace, but did you have buildscript defined in ScriptHolder?
I'm seeing this error while trying to upgrade Gradle 6.8 to 7.2 (and JUnit 4 to 5, etc.):
No signature of method: GradlePlugins.test() is applicable for argument types: (GradlePlugins$_run_closure5) values: [GradlePlugins$_run_closure5@4a6f4fd5]
Possible solutions: wait(), getAt(java.lang.String), use([Ljava.lang.Object;), wait(long), tap(groovy.lang.Closure), is(java.lang.Object)
This error is related to adding this code:
test {
useJUnitPlatform()
}
Any ideas on how to fix this?
I found it - I had to add:
class ScriptHolder {
...see gist...
Closure test
void test(Closure c) {
this.test = c
}
}
def test = holder.test.clone()
test.delegate = project.test
test()
@ysb33r, your approach has two drawbacks:
loadScriptByNameshouldn't contain apackagestatement.I looked for a solution and found out that much nicer and cleaner way is to compile plugin in
buildSrcand then apply its class to the main project. It is in the Gradle documentation.