Search code examples
gradledependenciessource-sets

Gradle sourceSet depends on another sourceSet


This Question is similar to Make one source set dependent on another

Besides the main SourceSet I also have a testenv SourceSet. The code in the testenv SourceSet references the main code, therefor I need to add the main SourceSet to the testenvCompile configuration.

sourceSets {
  testenv
}

dependencies {
  testenvCompile sourceSets.main
}

This does not work, because you cannot directly add sourceSets as dependencies. The recommended way to do this is:

sourceSets {
  testenv
}

dependencies {
  testenvCompile sourceSets.main.output
}

But this does not work correctly with eclipse, because when I clean the gradle build folder, eclipse can't compile anymore, since it depends on the gradle build. Also if I change main code I'd have to rebuild the project in gradle for the changes to take effect in eclipse.

How do I declare the dependencies correctly?

EDIT:

This

sourceSets {
  testenv
}

dependencies {
  testenvCompile files(sourceSets.testenv.java.srcDirs, sourceSets.testenv.resources.srcDirs)
}

works for the main source, but because I now reference the .java files I am missing generated classes from the Annotation-Processor :(


Solution

  • So after all this is the way to go:

    sourceSets {
      testenv
    }
    
    dependencies {
      testenvCompile sourceSets.main.output
    }
    

    To make it work correctly with eclipse you have to manually exclude all sourceSet outputs from the eclipse classpath. This is ugly, but it works for me:

    Project proj = project
    
    eclipse {
      classpath {
        file {
          whenMerged { cp ->
            project.logger.lifecycle "[eclipse] Excluding sourceSet outputs from eclipse dependencies for project '${project.path}'"
            cp.entries.grep { it.kind == 'lib' }.each { entry ->
              rootProject.allprojects { Project project ->
                String buildDirPath = project.buildDir.path.replace('\\', '/') + '/'
                String entryPath = entry.path
    
                if (entryPath.startsWith(buildDirPath)) {
                  cp.entries.remove entry
    
                  if (project != proj) {
                    boolean projectContainsProjectDep = false
                    for (Configuration cfg : proj.configurations) {
                      boolean cfgContainsProjectDependency = cfg.allDependencies.withType(ProjectDependency).collect { it.dependencyProject }.contains(project)
                      if(cfgContainsProjectDependency) {
                        projectContainsProjectDep = true
                        break;
                      }
                    }
                    if (!projectContainsProjectDep) {
                      throw new GradleException("The project '${proj.path}' has a dependency to the outputs of project '${project.path}', but not to the project itself. This is not allowed because it will cause compilation in eclipse to behave differently than in gradle.")
                    }
                  }
                }
              }
            }
          }
        }
      }
    }