# Configuring a custom Gradle sourceSet using a closure

**URL:** <https://discuss.gradle.org/t/configuring-a-custom-gradle-sourceset-using-a-closure/38624>\
**Category:** Help/Discuss\
**Created:** [December 24, 2020, 9:08am UTC](https://discuss.gradle.org/t/configuring-a-custom-gradle-sourceset-using-a-closure/38624 "2020-12-24T09:08:54Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![tudortimi](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/tudortimi/32/6369_2.png) [@tudortimi](https://discuss.gradle.org/u/tudortimi)\
**Post date:** [December 24, 2020, 9:08am UTC](https://discuss.gradle.org/t/configuring-a-custom-gradle-sourceset-using-a-closure/38624/1 "2020-12-24T09:08:54Z")

</div>

I’m trying to develop a Gradle plugin for a language I use (SystemVerilog). I’m still experimenting and figuring things out. Before I write the entire thing as a plugin, I thought it would be best to try out the different parts I need inside a build script, to get a feel of how things should work.

I already asked this question on [Stack Overflow](https://stackoverflow.com/questions/65436130/configuring-a-custom-gradle-sourceset-using-a-closure), but I’d like to add it here as well, as I see that this forum is pretty active and has the attention of the developers.

I’m trying to define a container of source sets, similar to how the Java plugin does it. I’d like to be able to use a closure when configuring a source set. Concretely, I’d like to be able to do the following:

```gradle
sourceSets {
    main {
        sv {
            include '*.sv'
        }
    }
}

```

I defined my own `sourceSet` class:

```gradle
class SourceSet implements Named {
    final String name
    final ObjectFactory objectFactory

    @Inject
    SourceSet(String name, ObjectFactory objectFactory) {
        this.name = name
        this.objectFactory = objectFactory
    }

    SourceDirectorySet getSv() {
        SourceDirectorySet sv = objectFactory.sourceDirectorySet('sv',
            'SystemVerilog source')
        sv.srcDir("src/${name}/sv")
        return sv
    }

    SourceDirectorySet sv(@Nullable Closure configureClosure) {
        configure(configureClosure, getSv());
        return this;
    }
}

```

I’m using `org.gradle.api.file.SourceDirectorySet` because that already implements `PatternFilterable` , so it should give me access to `include` , `exclude` , etc.

If I understand the concept correctly, the `sv(@Nullable Closure configureClosure)` method is the one that gives me the ability to write `sv { ... }` to configure via a closure.

To add the `sourceSets` property to the project, I did the following:

```gradle
project.extensions.add("sourceSets",
        project.objects.domainObjectContainer(SourceSet.class))

```

As per the Gradle docs, this should give me the possibility to configure `sourceSets` using a closure. [This site](https://docs.gradle.org/6.7.1/userguide/custom_gradle_types.html#nameddomainobjectcontainer), which details using custom types, states that by using `NamedDomainObjectContainer` , Gradle will provide _a DSL that build scripts can use to define and configure elements_ . This would be the `sourceSets { ... }` part. This should also be the `sourceSets { main { ... } }` part.

If I create a `sourceSet` for `main` and use it in a task, then everything works fine:

```gradle
project.sourceSets.create('main')

task compile(type: Task) {
    println 'Compiling source files'
    println project.sourceSets.main.sv.files
}

```

If I try to configure the `main` source set to only include files with the `.sv` extension, then I get an error:

```gradle
sourceSets {
    main {
        sv {
            include '*.sv'
        }
    }
}

```

I get the following error:

```gradle
No signature of method: build_47mnuak4y5k86udjcp7v5dkwm.sourceSets() is applicable for argument types: (build_47mnuak4y5k86udjcp7v5dkwm$_run_closure1) values: [build_47mnuak4y5k86udjcp7v5dkwm$_run_closure1@effb286]

```

I don’t know what I’m doing wrong. I’m sure it’s just a simple thing that I’m forgetting. Does anyone have an idea of what that might be?

---

<div class="post-metadata">

**Author:** ![tudortimi](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/tudortimi/32/6369_2.png) [@tudortimi](https://discuss.gradle.org/u/tudortimi)\
**Post date:** [December 25, 2020, 10:29am UTC](https://discuss.gradle.org/t/configuring-a-custom-gradle-sourceset-using-a-closure/38624/2 "2020-12-25T10:29:28Z")

</div>

I managed to solve it. I’ll post an answer later.

---

<div class="post-metadata">

**Author:** ![tudortimi](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/tudortimi/32/6369_2.png) [@tudortimi](https://discuss.gradle.org/u/tudortimi)\
**Post date:** [December 25, 2020, 8:35pm UTC](https://discuss.gradle.org/t/configuring-a-custom-gradle-sourceset-using-a-closure/38624/3 "2020-12-25T20:35:30Z")

</div>

It was a combination of poor copy/paste skills and the fact that Groovy is a dynamic language.

First, let’s look at the definition of the `sv(Closure)` function again:

```gradle
SourceDirectorySet sv(@Nullable Closure configureClosure) {
    configure(configureClosure, getSv());
    return this;
}

```

Once I moved this code to an own Groovy file and used the IDE to show me what is getting called, I noticed that it wasn’t calling the function I expected. I was expecting a call to `org.gradle.util.ConfigureUtil.configure` . Since this is part of the public API, I expected it to be imported by default in the build script. As [this page](https://docs.gradle.org/6.7.1/userguide/writing_build_scripts.html#script-default-imports) states, this is not the case.

To solve the issue, it’s enough to add the following import:

```gradle
import static org.gradle.util.ConfigureUtil.configure

```

This will get rid of the cryptic closure related error. It is replaced by the following error, though:

```gradle
Cannot cast object 'SourceSet_Decorated@a6abab9' with class 'SourceSet_Decorated' to class 'org.gradle.api.file.SourceDirectorySet'

```

This is caused by the copy/paste error I mentioned. When I wrote the `SourceSet` class, I drew heavily from `org.gradle.api.tasks.SourceSet` (and `org.gradle.api.internal.tasks.DefaultSourceSet` ). If we look at the `java(Closure)` method there, we’ll see it has the following signature:

```gradle
SourceSet java(@Nullable Closure configureClosure);

```

Notice that it returns `SourceSet` and not `SourceDirectorySet` like in my code. Using the proper return type fixes the issue:

```gradle
SourceSet sv(@Nullable Closure configureClosure)

```

With this new return type, let’s look again at the configuration code for the source set:

```gradle
sourceSets {
    main {
        sv {
            include '*.sv'
        }
    }
}

```

Initially, I thought it was supposed to work as follows: pass `main { ... }` as a `Closure` to `sourceSets` , pass `sv { ... }` as a `Closure` to `main` , and handle the `include ...` part inside `sourceDirectorySet` . I banged my head against the wall for a while, because I couldn’t find any code in that class hierarchy that takes closures like this.

Now, I think the flow is slightly different: pass `main { ... }` as a `Closure` to `sourceSets` (as initially thought), but call the `sv(Closure)` function on `main` (of type `sourceSet` ), passing it `{ include ... }` as the argument.

Bonus: There was one more issue that wasn’t related to the “compile” errors I was having.

Even after getting the code to run without errors, it still wasn’t behaving as expected. I had some files with the `*.svh` extension that were still getting picked up. This is because, when calling `getSv()` , it was creating a new `SourceDirectorySet` each time. Any configuration that was done previously was getting thrown away each time that this function was called.

Making the `sourceDirectorySet` a class member and moving its creation to the constructor fixed the issue:

```gradle
private SourceDirectorySet sv

SourceSet(String name, ObjectFactory objectFactory) {
    // ...
    sv = objectFactory.sourceDirectorySet('sv',
            'SystemVerilog source')
    sv.srcDir("src/${name}/sv")
}

SourceDirectorySet getSv() {
    return sv
}

```

---

<div class="post-metadata">

**Author:** ![Chris\_Dore](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/chris_dore/32/7592_2.png) [@Chris\_Dore](https://discuss.gradle.org/u/Chris_Dore)\
**Post date:** [December 26, 2020, 6:15am UTC](https://discuss.gradle.org/t/configuring-a-custom-gradle-sourceset-using-a-closure/38624/4 "2020-12-26T06:15:55Z")

</div>

> [@tudortimi](#):
>
> I was expecting a call to `org.gradle.util.ConfigureUtil.configure` . Since this is part of the public API

Side note; it’s not part of the “public API”, at least in terms of APIs with some level of backwards compatibility management. That’s also why it does not appear in the online javadoc.  
[https://docs.gradle.org/current/userguide/authoring\_maintainable\_build\_scripts.html#sec:avoiding\_gradle\_internal\_apis](https://docs.gradle.org/current/userguide/authoring_maintainable_build_scripts.html#sec:avoiding_gradle_internal_apis)

The `NamedDomainObjectContainer` returned by `ObjectFactory.domainObjectContainer` has a [`configure(Closure)`](https://docs.gradle.org/current/javadoc/org/gradle/api/NamedDomainObjectContainer.html#configure-groovy.lang.Closure-) method that you could use.

---

<div class="post-metadata">

**Author:** ![tudortimi](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/tudortimi/32/6369_2.png) [@tudortimi](https://discuss.gradle.org/u/tudortimi)\
**Post date:** [December 27, 2020, 2:58pm UTC](https://discuss.gradle.org/t/configuring-a-custom-gradle-sourceset-using-a-closure/38624/5 "2020-12-27T14:58:48Z")

</div>

> [@Chris\_Dore](#):
>
> The `NamedDomainObjectContainer` returned by `ObjectFactory.domainObjectContainer` has a [`configure(Closure)`](https://docs.gradle.org/current/javadoc/org/gradle/api/NamedDomainObjectContainer.html#configure-groovy.lang.Closure-) method that you could use.

I’m not sure what you mean by this? How could I use it?

(Please keep in mind that I’m a Gradle/Groovy n00b.)

---

<div class="post-metadata">

**Author:** ![Lenra](https://sea1.discourse-cdn.com/gradle/user_avatar/discuss.gradle.org/lenra/32/9002_2.png) [@Lenra](https://discuss.gradle.org/u/Lenra)\
**Post date:** [December 29, 2020, 4:45pm UTC](https://discuss.gradle.org/t/configuring-a-custom-gradle-sourceset-using-a-closure/38624/6 "2020-12-29T16:45:24Z")

</div>

I have created a Gradle plugin to create Gradle plugins for programming languages. You can find the project here : [https://gitlab.com/lenra/gradle-plugins/gradle-language-plugin](https://gitlab.com/lenra/gradle-plugins/gradle-language-plugin). It’s not finished, but it might help you (using it or for understanding).
