Need BuildSrc to depend on a subproject


(Phil Swenson) #1

we have code in BuildSrc at the root of the project (clean database task). This code needs to access the CleanDatabase class that lives in a subproject.

How do we declare this dependency?

thanks


(Peter Niederwieser) #2

It’s impossible. ‘buildSrc’ is a separate build that needs to run strictly before the main build.

One way to solve this problem is to split off ‘CleanDatabase’ and related classes into a separate build, publish them to a repository, and declare a binary dependency on them in ‘buildSrc’.


(Phil Swenson) #3

Thanks Peter. This is why I wish Gradle ran in a true interpreted mode (like Ruby).


(Peter Niederwieser) #4

I wonder if that would help. Having the build depend on what is to be built is, in general, a catch-22.


(Phil Swenson) #5

if gradle was interpreted, the task in question (cleanDatabase) wouldn’t care if the classes it needed were there until runtime. So as long as you compiled the classes you needed before you executed cleanDatabase - there would be no prob. And you could have the cleanDatabase task depend on the compile task.

Ant doesn’t have this problem either as it’s interpreted.


(Luke Daley) #6

Really? You can build ant taskdefs as part of your build and use them in the same build?


(Peter Niederwieser) #7

@Phil: Gradle is based on Groovy, which is a compiled language. I agree that this particular problem would be somewhat simpler to solve with an interpreted language, but you’d still have to do the wiring (i.e. the classes would have to be made available to the task). It shouldn’t be that hard to solve this problem with Gradle either. The task could create its own class loader and load the classes from there. Or it could use a GroovyShell to run its ‘main’ code, with the classes on the shell’s class path.


(Phil Swenson) #8

@Luke if you are using JRuby, you can reference Java Classes in your build script like and they aren’t evaluated until runtime execution for that task. Something like:

task :cleanDB => :compile do
    dbUtil = com.myco.DBUtil.new
    dbUtil.clean
end

This may not work the first time though as I am not sure if JRuby can dynamically add classes to its classpath. But at the very least, it would let you run compile first then get the DBUtil compiled. Then you could run cleanDB and it would be successful.

so:

ruby>
rake compile
> compile completed
ruby> rake cleanDB
> cleaning DB....
> Clean completed

The other approach is calling ant tasks via rake and have ant fork the process for executing the DBClean, then you wouldn’t need two steps.


(Phil Swenson) #9

@Peter, @Luke

I’m not sure if I follow your suggestions. Do you have something more specific? I thought of using JavaExec, but that’s pretty ugly. It would work though.

The approach I’m currently pursuing is to create a DevUtil jar file that I check into source control. It would contain all the code that I need for these sort of dev convenience/automation tasks like this. But it is awkward.

I think it would be useful to have a best practices for this sort of thing. I have noticed that the ruby community is way more into automation than the java community and issues like this are probably why. In Ruby you always have access to your code base for automation purposes because of its interpreted nature. I suspect there is some way to get a more interpreted effect with gradle (dynamically loading classes?)


(Peter Niederwieser) #10

I don’t see how JavaExec would solve the problem. GroovyShell seems like a straightforward solution, so I’d try that first.


(Phil Swenson) #11

@Peter I will look at groovy shell. But here is how JavaExec solves the prob:

task start(type: JavaExec) {
   main = "com.myco.BlahClass"
   systemProperties = runAESysProps
   classpath = sourceSets.main.runtimeClasspath
   args('start')
   description = "Start Analytic Engine."
}

So I can call a method on a class that hasn’t’ been compiled yet and gradle doesn’t throw an exception at build.gradle compile time. It wouldn’t work at runtime until the classes are compiled of course.

I think this is ugly, but it does work.


(Peter Niederwieser) #12

This only works if the task doesn’t have any code of its own. But in that case, it’s a good solution.


(Phil Swenson) #13

@Peter I would like to try the GroovyShell approach. It makes sense, pass along a “string” to the shell that gets evaluated at runtime. But I can’t find any examples or mention of this in the doc.

Do you know of any examples?

thx


(Luke Daley) #14

http://groovy.codehaus.org/Embedding+Groovy