buildSrc access to project modules?


(Jesper Thuun-Petersen) #1

I want to create my own plugin type to ease access to our home-grown code generator. The code generator is in a module called ‘remoteserviceframework’.

I have my plugin in the buildSrc directory, and I therefore add a dependency to “:remoteserviceframework” from the top level build.gradle.

Now, everything compiles and looks great in IntelliJ.

Running my build however, my plugin is not recognized.

it is declared in a class like this:

class RemoteService implements Plugin {

void apply(Project project) { … }

and when I apply it, I do so with:

apply plugin: ‘RemoteService’

This, however, is not recognized as a plugin.

Am I missing something here? Is it not an option to have plugins access modules from the project?


(Peter Niederwieser) #2

‘buildSrc’ is its own build, and is executed before even the evaluation phase of the main build starts. Therefore, you can’t use outputs of the main build from ‘buildSrc’. Sometimes it’s possible to work around this by configuring a source directory of the main build as a source directory of the ‘buildSrc’ build (effectively building it twice), but you’ll have to know what you are doing.


(Jesper Thuun-Petersen) #3

Peter,

thanks for the quick answer! I understand the problem, but I’d really like to create a plugin for this, and I’d prefer not to build and deploy it as a separate project.

Would it be possible to put my plugin code in the remoteserviceframework module, and still be able to use it via ‘apply plugin’ from other modules?

If not, how do I add a source to the buildSrc?

Thanks! /Jesper Thuun-Petersen


(Peter Niederwieser) #4

Would it be possible to put my plugin code in the remoteserviceframework module, and still be able to use it via ‘apply plugin’ from other modules?

No, it isn’t possible.

If not, how do I add a source to the buildSrc?

Add a ‘build.gradle’ in ‘buildSrc’, and then add a source directory to the ‘main’ source set as usual.


(Jesper Thuun-Petersen) #5

OK, thanks.

I realize this might be too heavy a task to accomplish something fairly simple, so I decided to go with:

compileJava <<{
    InterfaceGenerator ig = new InterfaceGenerator()
    ig.generate('com.stibo.services.workbench.beans',
            'com.stibo.services.workbench.interfaces',
            project.buildDir.toString + '/generated-src/remoteservice')
}

Now, we may be back at the same problem? Because the InterfaceGenerator, which is a class in the remoteServiceFramework, which I have a compile dependency on, cannot be found at this point. How do I get the class on my build class path?


(Peter Niederwieser) #6

As I’ve tried to explain already, you cannot use outputs of the main build from the ‘buildSrc’ build. One workaround, applicable in some but not all cases, is to add the required code as a source directory of the ‘buildSrc’ build, effectively building it twice.


(Jesper Thuun-Petersen) #7

Hi Peter, I did understand that.

I’m sorry, if I didn’t explain my new approach properly:

I’ve abandoned the plugin approach. I’m just doing plain gradle files now. In the build-script of one module, I want to call compiled code from another module. Is that possible?

Regards /Jesper


(Peter Niederwieser) #8

You can’t, for exactly the same reasons.


(Jesper Thuun-Petersen) #9

Thanks Peter,

For reference, I solved the problem using ant, as my plugin now includes the following code:

ant.java(classname: 'com.stibo.remoteserviceframework.server.impl.InterfaceGenerator', fork: 'true', failOnError: 'true') {
                arg(value: "${sourcePackage}")
                arg(value: "${destinationPackage}")
                arg(value: "${destinationDir}")
                sysproperty(key: "FRAMEWORK_DISABLE_AUTOINJECT", value: "true")
                classpath {
                    pathelement(path: project.sourceSets.main.output.asPath)
                    pathelement(path: project.sourceSets.main.compileClasspath.asPath)
                    pathelement(location: "${project.mainProject}/remoteserviceframework/build/libs/remoteserviceframework-1.0-SNAPSHOT.jar")
                }
            }

the interesting point is the direct reference to the artifact containing my code generator. Probably not the most elegant way of handling the problem, but it takes care of my problem for now.


(Peter Niederwieser) #10

Running the code generator in a separate process is a good solution (probably better than fussing with a class loader in the build script). Instead of ‘ant.java’, you could use a ‘JavaExec’ task.