Dependency on subproject not resolved


#1

I have a multimodule build in which one module creates an application via the “application” plugin and another module executes the created application. However, executing the second module does not trigger creation of the application zip and results in the following error:

Cannot expand ZIP ‘C:\myproject\application\build\distributions\application-1.0.0-SNAPSHOT.zip’ as it does not exist.

I have the following configuration in the second module:

configurations {
   theApplication
}

dependencies {
	theApplication project(path: ':application', configuration: 'archives')
}
	
task extractApplication(type: Copy) {
  from { 
  	configurations.theApplication.findAll { it.name.endsWith '.zip' }.collect { zipTree(it) }
  }
  into "$buildDir/tmp"
}

Why running the “extractApplication” task does not trigger creation of the application archives and how to fix it?

Edit: I managed to work around the problem by adding the dependency to the “extractApplication” task:

dependsOn(":application:assembleDist")

Is it the correct solution or there is a better one?


(Alexander Volanis (HPE)) #2

That is not the correct solution. The correct solution is to instrument the :application project like this:

configurations {
  theApplication
}
artifacts {
  theApplication assembleDist
}

Then in your second module you change the code to this:

configurations {
   theApplication
}

dependencies {
	theApplication project(path: ':application', configuration: 'theApplication')
}
	
task extractApplication(type: Copy) {
  dependsOn configurations.theApplication

  from {
    zipTree(configurations.theApplication.singleFile)
  }
  into "$buildDir/tmp"
}


#3

Thanks for the reply.

Can you elaborate why declaring dependency on configuration is better than on a task?


(Alexander Volanis) #4

Because it uses the Gradle preferred mechanism to link outputs of one task to inputs of another. Gradle relies on the ability to correctly define the input/output of any one task and uses this information to generate task dependency graphs. Directly using the dependsOn mechanism with a task accomplished the same thing but it causes your project to be intimately coupled with the structure of the sibling project. Using the configuration names as handles is better because you no longer assume any special knowledge of how the artifacts are constructed, you just need to know there is an output artifact declared for the configuration named in the dependency. In essence the project, like the task is able to declare its outputs so sibling projects can make references.

This also works to make the correct POM files with usage of dependencies, the way you were doing it the dependencies of the project you are calling into are not visible to the consumer.