How to reference build/classes/main in buildscript dependencies?

I have a buildscript block that contains build/classes/main as a dependency.

buildscript {
    dependencies {
        classpath files('build/classes/main')
    }
}

This is because I have a plugin that compiles some Java into that directory before it runs a second step. The second step is failing with a ClassNotFoundException because it can’t find the class that it previously compiled into build/classes/main.

But this only happens after a clean checkout. If I run a clean build a second time it works. So it looks as though Gradle is determining its buildscript classpath before it runs any tasks and it is picking up the classes that were left over from the previous build. For a clean checkout there are no previous classes.

How can I change things so that the classes compiled in the first step are visible to the second step?

This is what the buildSrc directory is designed for. Your plugin would be built there and automatically be included on the buildscript classpath.

Thanks for the response Chris.

I think you may have misunderstood my question. Probably my fault.

It’s not the plugin that is being compiled into build/classes/main. The plugin itself is a code generator that generates code based on a model descriptor that is written in Java. So the first thing the plugin must do is compile that model descriptor and it puts the output in build/classes/main. That part is working fine. The next thing the plugin does is run the code generator using the compiled model descriptor as input. But this step is failing because the .class file of the descriptor is not on the classpath, even though it does exist in the build dir at the time the generator task is run.

It looks as though the classpath files(‘build/classes/main’) dependency notation is not adding a directory to the classpath but instead is scanning the directory and putting the individual classes on the classpath. But it does this before the class I need actually exists there.

So I guess the question is…How do I add a directory to the buildscript classpath?

If I understand you correctly, you are trying to use the plugin to generate code that is to be used by the buildscript. I don’t think there is any way to get that to work the way you want. The plugin will be generating code long after Gradle has evaluated projects and like you’ve observed, the classes are not available. If you apply the plugin to the buildSrc project’s build.gradle and generate your code there, then the generated classes should be available for use in the root project’s buildscript. This is because the buildSrc project is executed before the regular project build.

Thanks very much Chris. That worked.

I moved just my model descriptor class to a buildSrc folder and it does the job perfectly.

Many thanks

You shouldn’t use buildscript.classpath for these use cases. Instead your plugin should take a classpath argument (a FileCollection) that the individual projects can fill in, e.g. with sourceSets.main.output. The plugin then creates an UrlClassLoader to load the descriptor from the given FileCollection.

1 Like

Hi Stefan,

Thanks for the response.

I’m guessing your suggestion for doing it that way is to reduce the items on my plugin’s classpath to just those things that it requires and not everything that anything else in the buildscript may require.

I’ll have to read up on how to use a UrlClassLoader.

Thanks,
Kevin

Yes, it also makes the plugin simpler to use, because users don’t have to mess with the buildscript block or put things in buildSrc.