Gradle dependency on non-main source set module

Answered

We have a multi-project Gradle build that includes some JSPs that reference tag libraries located in one of the modules.  The project structure is like this:

:server:api

:server:modules:X

:server:modules:Y

The api project has multiple source sets, including "main" and "webapp".  It is the "webapp" source set that contains the tag lib source. Projects X and Y both also have multiple source sets, including "main" and "jsp".  

In IntelliJ, we use the Gradle Tool window's sync button to generate our .iml files for all the projects.  This works great for most everything, but the tag libraries cannot be found ("Cannot resolve taglib with URI: ...").  I can manually add api_webapp as a module dependency to X_main and the taglib is resolved, but I cannot find a way to declare the dependency within Gradle so the sync within IntelliJ will generate the dependency automatically.  

I tried declaring an explicit compile dependency between X and the webapp configuration of api, but that is just seen as a declaration of a dependency on api with no distinction for the IntelliJ source set module.

After reading this post, I added this to projects X and Y, but to no avail.
project.apply plugin: 'idea'
project.idea {
module {
scopes.COMPILE.plus += [ project.project(":server:api").configurations.webappCompile ]
}

And, given that we are directing developers to generate the .iml files using the Gradle sync, I would prefer not to use the idea plugin and bring in those tasks that we actually don't want anyone to use (especially since there doesn't seem to be a way to tell those tasks to generate files in the .idea directory), but we might accept that tradeoff if this plugin gets us what we need.

So, is there a way to declare a dependency between X and api_webapp that I'm not seeing?

Thanks!

Susan

0
4 comments
Avatar
Permanently deleted user

We have figured out a way past this.  We declare a compile dependency on the tld files for projects that need them.  This is hacky in a number of ways (e.g., Is there a better way to say "if (IntelliJ)" in Gradle?), but we will proceed with this for now.

// We need this declaration for IntelliJ to be able to find the .tld files, but if we include
// it for the command line, there will be lots of warnings about .tld files on the classpath where
// they don't belong ("CLASSPATH element ... is not a JAR."). These warnings may appear if
// building within IntelliJ, but perhaps we can live with that (for now).
if (System.properties.'idea.active')
project.dependencies.add("compile", project.rootProject.tasks.copyTagLibsBase.inputs.files)
0

You've found an outdated post about the custom sourceSet support. IntelliJ added the support for custom gradle source sets and configurations a long time ago. Actually you should be able to drop any IDE specific code from your build scripts (at least if your project configuration can be imported w/o such workarounds).

The question how do you configure your dependency on the ':api' webapp source set? 

Could you try the following configuration below? Does it help?

I put all gradle configuration into the root project build.gradle for simplicity

settings.gradle

rootProject.name = 'server'
include 'api', 'modules:X', 'modules:Y'

build.gradle

group 'server'
version '1.0-SNAPSHOT'

configure(subprojects - project(":modules")) {
group 'server'
version '1.0-SNAPSHOT'
apply plugin: 'java'
sourceCompatibility = 1.8
}

project(":api") {
sourceSets {
webapp
}
// build webapp JAR and add a webapp configuration
configurations {
webapp
}
task webappJar(type: Jar) {
classifier 'webapp'
from project.sourceSets.webapp.output
group 'build'
description 'Assembles a jar archive containing the tag lib source.'
}
artifacts {
webapp webappJar
}
}

def webProjects = [project(":modules:X"), project(":modules:Y")]
configure(webProjects) {
sourceSets {
jsp
}
dependencies {
compile project(path: ':api', configuration: 'webapp')
}
}

1

Hi,

The question here seems to be:
Do Gradle Java Dependency Configurations include the corresponding SourceSets or not (could not find a clear answer here: https://docs.gradle.org/current/userguide/java_plugin.html#tab:configurations)?

From what Vladislav Soroka suggests (and what Gradle itself does), the answer seems to be yes, but on my end (and also on Susan Hert's end), IntelliJ seems to think the answer is no.

I am attaching a screenshot from a multi-project gradle build (Wrapper project + projects sub1, sub2). sub1 defines a dependency on

testCompile project(path: ':sub2', configuration: 'testCompile')

This adds all test dependencies of project :sub2 to project :sub1's test dependencies, but it does not add :sub2's own test code (see junit.Assert vs. ExampleTestSub2 in the screenshot).

Is this a bug?

As a workaround, I found that adding the following line to sub1's build.gradle tells IntelliJ to also include sub2's test code:

testCompile project(':sub2').sourceSets.test.output

But then, I have to also include:

project.evaluationDependsOn(':sub2')

0

You can see how Gradle configures dependencies for source sets by running Gradle dependencies report. Can you build such project from command line by Gradle? See this discussion for setting up such dependencies for test classes: https://discuss.gradle.org/t/gradle-test-classes-needed-in-another-sub-project/13365/6

0

Please sign in to leave a comment.