I got a problem in triggering a build of a dependency.
Let me give you a picture of the situation: I have several native C++ projects, in which, for example, project Framework" depends on project “Reports engine”, ad so on. As showed in the following illustration, these are
versioned dependencies. To manage this situation, I decided to use a single Git repository containing all projects, in which every project:
- has its own dependency file with a map {projectName, version}
- on every Git push is processed by Jenkins, which build, test, version, and finally publish on Artifactory a tar with the binary (generally, a .so file) and the public headers
- is versioned with its last Git commit
This configuration allows for example to link a project currently developed on a specific Git branch, with a
library produced by another developer in another branch. Beside this situation, there is also another (obvious) option: I could be creating new features requesting concurrent changes both in project “Framework” and in project “Reports engine”. This is rather a common situation, that I know could be perfectly managed by Gradle multiproject build.
However, because I thought this kind of build would be incompatible with the “versioned” kind first described, I decided to consider every dependency as a PrebuiltLibrary. When the dependency has a version number, it’s searched inside a default folder (e.g., “/home/devel/libs”): if it’s not found, it’s downloaded from Artifactory. When it has no version number, it’s searched in the project directory (e.g. “/home/devel/workspace/ReportsEngine/build/binaries/ReportsEngineSharedLibrary/release/”): if it’s not found, a Gradle build should be triggered.
This is an extract from my gradle.build (N.B.: every project has a symbol link to the same build.gradle, which is located in the parent directory):
model {
repositories {
libs(PrebuiltLibraries) {
prebuiltLibrariesList.each {
delegate."$it"{
def libraryName = "${name}"
def version = versions."${libraryName}"
if(version) {
def libraryType = "SharedLibrary"
//Headers path
def libraryHeadersSrcDir = "../${libraryName}"
if(versions."${libraryName}" != "local") {
libraryHeadersSrcDir = "${baseDir}/lib/${libraryName}/" + version + "/headers"
}
headers.srcDir "${libraryHeadersSrcDir}"
binaries.withType(SharedLibraryBinary) {
if("${targetPlatform.name}" == "x86" || "${targetPlatform.name}" == "x64") {
def versionedDependenciesFile = "../${libraryName}/dependencies.gradle"
//Local path
def realFileLocation = "../${libraryName}/build/binaries/${libraryName}${targetPlatform.name}${libraryType}/${buildType.name}/lib${libraryName}${targetPlatform.name}.so"
//If it's a versioned dependency, we look
for it in the default path, and if it's not present we download it from
Artifactory
if(versions."${libraryName}" != "local") {
realFileLocation = "${baseDir}/lib/${libraryName}/" + version + "/libs/${libraryName}${targetPlatform.name}${libraryType}/${buildType.name}/lib${libraryName}${targetPlatform.name}.so"
versionedDependenciesFile = "${baseDir}/lib/${libraryName}/" + version + "/dependencies.gradle"
def realFile = file(realFileLocation)
if( !realFile.exists() ) {
tasks.create(name: "download${libraryName}${targetPlatform.name}${buildType.name}FromArtifactory", type: ArtifactoryDownloader) << {
originPath = "staging-local/organization/${libraryName}"
artifactName = "${libraryName}-${version}.zip"
destinationPath = "${baseDir}/lib/${libraryName}/" + version
}
//!!!!!!!!!!!!! When building the
current project, the dependency must be downloaded first
project.tasks["${buildType.name}${capitalizedProjectName}${targetPlatform.name}SharedLibrary"].dependsOn( project.tasks["download${libraryName}${targetPlatform.name}${buildType.name}FromArtifactory"] )
}
}
//If it's a local dependency, we look for
it in its project build path, and if it's not present we build it
else {
def realFile = file(realFileLocation)
if( !realFile.exists()) {
File buildFilePath = file("${file("${p_d_as_string}").getParentFile()}/${libraryName}/build.gradle")
project.tasks.create(name: "build${libraryName}${targetPlatform.name}${buildType.name}", type: GradleBuild) << {
buildFile = file("${file("${p_d_as_string}").getParentFile()}/${libraryName}/build.gradle")
startParameter.projectProperties.'subprojectDir' = "${file(p_d_as_string).getParentFile()}/${libraryName}"
dir = "${file(p_d_as_string).getParentFile()}/${libraryName}"
tasks = [ "${buildType.name}${libraryName.capitalize()}${targetPlatform.name}${libraryType}" ]
}
//!!!!!!!!!!!!! When building the current project, the dependency must be built first
project.tasks["${buildType.name}${capitalizedProjectName}${targetPlatform.name}${libraryType}"].dependsOn( project.tasks["build${libraryName}${targetPlatform.name}${buildType.name}"] )
}
}
}
}
}
}
}
}
}
}
The dependsOn method should state for example that the task “buildFrameworkx86SharedLibrary” should run after the task “buildReportsEngineSharedLibraryx86SharedLibrary”. This task in turn should call the task “buildReportsEnginex86SharedLibrary”. Unfortunately, nothing happens instead.
As you can see, I set the GradleBuild task as an execution task, because it is the phase in which it should be called. I tried also setting it as a configuration task, but the problem still remains.
Do you have any suggestion to solve this problem?
Thank you very much,
Mauro