Adding directory as a source set, filtering only this directory

Hello, I am trying to add a resource directory to the source sets, but making sure that only some files are included.

Say that we have the following files:

src/
  main/
    other/
      other-1
      other-2
    resources/
      resources-1

and that my objective is to create a JAR file including other-1 and resources-1, but not other-2.

I have tried with:

sourceSets {
  main {
    resources {
      srcDir(files('src/main/other') {
        include 'other-1'
      })
    }
  }
}

Which results in a JAR file containing only the other-1 file.

I have noticed that files does not have an include method. So I would have expected the above to fail. Instead it seems to just apply the include as if it was within the resources block. Which in fact does explain why the generated JAR file contains only the other-1 file.

So, I understand that my approach is wrong and I have tried some variants that did not work.

Is there any way to achieve the expected result?

I guess Multiple SourceSets with include option is basically about the same issue.

So maybe it is just not doable.

The workaround that I came up with is to not add a source set, but instead add the file when generating the JAR:

tasks.withType(Jar) {
  from('src/main/other') {
    include 'other-1'
  }
}

The problem with such approach is when integrating with other tools (eg. Eclipse).

If I am using other-1 file in a test case then running the test from Eclipse fails, as Eclipse uses the source files during the test.

What you are after is using fileTree instead of files.
files would anyway only contain the directory “other” so the include would not have worked even if the method would have been there.
fileTree on the other hand contains all the files with path information in the directory you specified so there you can then use include.


I also recommend switching to Kotlin DSL. By now it is the default DSL, you immediately get type-safe build scripts, actually helpful error messages if you mess up the syntax and amazingly better IDE support.

In this case you could for example easily have found out that include is in the parent context by writing this. in front of it for a second:

Thanks Björn.

I gave the fileTree a try, but the srcDir does not seem to like it because instead of a directory it receives an array of files.

So I tried:

sourceSets {
  main {
    resources {
      srcDir(fileTree("src/main/other"))
    }
  }
}

and the error was:

> Source directory '.../src/main/other/other-1' is not a directory.

It seems that files does not provide the filtering aspect that I would like to use, while fileTree does but it is too fine grained, in the sense that it returns the list of files that should be included but on the other hand does not keep a “reference” to the directory that was originally provided (in my case “src/main/other”).

… or maybe I am just approaching this wrong, my Gradle knowledge is admittedly quite limited.

Ah, if it does not like filetrees, you probably need a second source set.
Something like:

sourceSets {
   other {
      resources {
         srcDir("src/main/other")
         include("other-1")
      }
   }
   main {
      resources {
         source(other.resources)
      }
   }
}
1 Like

Ah yes, that works perfectly for my use case.

And I really like it’s simplicity, I don’t think I would have come up with such a solution.

:+1:

Danke viel mal Björn.

1 Like