Repository: incubator-edgent Updated Branches: refs/heads/master a30ed5aea -> 3118af669
[WIP] Quarks-240 [gradle] manifest classpath and ext deps - set manifest classpath (sans project's external deps) - TODO stage core external dependency jars - TODO stage project's external dependency jars Project: http://git-wip-us.apache.org/repos/asf/incubator-edgent/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-edgent/commit/5ad89266 Tree: http://git-wip-us.apache.org/repos/asf/incubator-edgent/tree/5ad89266 Diff: http://git-wip-us.apache.org/repos/asf/incubator-edgent/diff/5ad89266 Branch: refs/heads/master Commit: 5ad892666965376283e8675bfdd8319e0e214f37 Parents: a30ed5a Author: Dale LaBossiere <dlab...@us.ibm.com> Authored: Tue Aug 30 10:54:52 2016 -0400 Committer: Dale LaBossiere <dlab...@us.ibm.com> Committed: Tue Aug 30 10:54:52 2016 -0400 ---------------------------------------------------------------------- build.gradle | 232 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 201 insertions(+), 31 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-edgent/blob/5ad89266/build.gradle ---------------------------------------------------------------------- diff --git a/build.gradle b/build.gradle index c65bf09..e4f5405 100644 --- a/build.gradle +++ b/build.gradle @@ -25,7 +25,7 @@ allprojects { url 'https://repo.eclipse.org/content/repositories/paho-snapshots/' } } - + project.version = build_version } @@ -55,7 +55,15 @@ ext { target_docs_dir = "${ext.target_dir}/docs" target_javadoc_dir = "${ext.target_docs_dir}/javadoc" target_report_dir = "${ext.target_dir}/reports" + + // project groups whose jars are to be placed in target_java8_lib + // instead of the default "$target_java8_dir/$simpleProjectGroup/$project.name/lib" + // e.g., "$target_java8_dir/lib" for api/topology + // "$target_java8_dir/connectors/iotp/lib" for connectors/iotp + // + target_java8_lib_groups = ["api", "providers", "runtime", "spi"] + // TODO can these be deduced by the absence of a build.gradle for the project? aggregatorOnlyProjects = [ ':analytics', ':api', ':apps', ':connectors', ':console', ':providers', @@ -66,8 +74,167 @@ ext { filteredSubprojects = subprojects*.findAll { project -> !aggregatorOnlyProjects.contains(project.path) } + + // for manifest classpath hackery + jarNameToProjectMap = [:] // e.g., "edgent.connectors.iotp-0.4.0.jar" => Project(':component:iotp') + projectToJarNameMap = [:] +} + +def recordProjectJar(Project proj) { + // manifest classpath hackery: update maps of project's jar <=> Project + def jarName = "${proj.group}.${proj.name}-${project.version}.jar" + jarNameToProjectMap[jarName] = proj + projectToJarNameMap[proj] = jarName + //println "#### updated jar <=> project maps: "+"$proj : $jarName" +} + +def String mkJarNameFromSpec(String jarSpec) { + // e.g. 'com.google.code.gson:gson:2.2.4' => gson-2.2.4.jar + return jarSpec.split(':')[1] + '-' + jarSpec.split(':')[2] + '.jar' } +def String stripJarNameVersion(String jarName) { + // e.g., edgent.api.topology-0.4.0.jar => edgent.api.topology.jar + return jarName.substring(0, jarName.lastIndexOf('-')) + '.jar' +} + +def String getSimpleProjectGroup(Project proj) { + // e.g., 'edgent.api' => 'api' + return "$proj.group".replace("edgent.", "") +} + +// create a path to dir2 relative to dir1 +// e.g., dir1:'lib', dir2:'connectors/iotp/lib' => ../connectors/iotp/lib +def String mkRelativePath(File dir1, File dir2) { + def relPath = dir1.toPath().relativize(dir2.toPath()) + //println "#### relPath: "+relPath+" dir1:"+dir1+" dir2:"+dir2 + return relPath.toString() +} +def String mkRelativePath(String dir1, String dir2) { + return mkRelativePath(new File(dir1), new File(dir2)) +} + +// e.g., => "lib" or "<component>/<subcomponent>/lib" +def String getRelProjectDirInTargetDir(Project proj, String kind) { // kind: "lib", "ext" + // the general case location + def simpleProjectGroup = getSimpleProjectGroup(proj); + def relProjDir = "$simpleProjectGroup/$proj.name/$kind" + + // special cases + if (target_java8_lib_groups.contains(simpleProjectGroup)) { + relProjDir = "$kind" + } + else if ('samples' == simpleProjectGroup) { + relProjDir = "$simpleProjectGroup/$kind" + } + + return relProjDir +} + +// Get paths relative to the project's dir in the target-dir +// to the project's immediate-only dependant project's jars +// in their project's dir in the target dir +// +// e.g., returns ['../../../lib/edgent.api.topology.jar', ...] +def Collection getRelDirectDependantProjJars(Project proj) { + //println "#### proj: " + proj + + def directDependantProjects = proj.configurations.compile.dependencies + .withType(ProjectDependency.class) + .collect { it.dependencyProject } + //println "#### directDependantProjects: " + directDependantProjects + + def directDependantProjJars = directDependantProjects.collect { + def relProjDirInTarget = getRelProjectDirInTargetDir(it, 'lib') + def jarName = projectToJarNameMap[it] + "$relProjDirInTarget/$jarName" + } + + // make relative paths from the project's dir in targetDir to the + // jars in the dependent projects' dir in targetDir + def myProjDirInTargetDir = getRelProjectDirInTargetDir(proj, 'lib') + def relDependantJars = directDependantProjJars.collect { + mkRelativePath(myProjDirInTargetDir, it) + } + //println "#### relDependantJars: "+relDependantJars + return relDependantJars +} + +// e.g., returns ['../../../ext/gson-2.2.4.jar', ...] +def Collection getRelCoreExtDependantJars(Project proj) { + // make relative paths from the project's dir in targetDir to the + // "ext" dir in targetDir + def myProjDirInTargetDir = getRelProjectDirInTargetDir(proj, 'lib') + def relDependantJars = ext_classpath.collect { + jarSpec -> + def jarName = mkJarNameFromSpec jarSpec + def relativeDependantJarDir = mkRelativePath(myProjDirInTargetDir, 'ext') + "$relativeDependantJarDir/$jarName" + } + //println "#### relDependantJars: "+relDependantJars + return relDependantJars +} + +def String mkManifestClassPath(Project proj) { + // The manifest's classpath needs to include the project's: + // - immediate-only dependant edgent jars (not transitive and not their ext deps) + // - immediate dependant external jars and their transitive deps + // - the core_ext_dependency jars + + // TODO note: core_ext jars and their staging path ... + + def depProjJars = getRelDirectDependantProjJars proj + depProjJars = depProjJars.collect { stripJarNameVersion it } + + // TODO def projExtJars = getRelProjExtDependantJars proj + def projExtJars = [] + + // unfortunate to include these if project didn't declare them as a dependency + // TODO related to come: sample common jars + def coreExtJars = getRelCoreExtDependantJars proj + + def jars = [] + jars.addAll depProjJars + jars.addAll projExtJars + jars.addAll coreExtJars + + def classPathStr = jars.join(' ') + //println "#### "+proj+" manifest classPath: "+classPathStr + return classPathStr +} + +// ================================================================== +// floundering trying to get a project's direct dependant project's +// jars using the gradle object model. +// +// A hacky way now seems to be: +// - identify the direct dependant projects +// - formulate the jar name for each +// - get all of the configuration's files (ends up transitive) and +// filter to select only those for direct dependent projects + +def Collection getDirectDependantProjJarsXXX(Project tgtProj) { +println "#### tgtProj: " + tgtProj + + def directDependantProjects = tgtProj.configurations.compile.dependencies + .withType ProjectDependency.class +println "#### directDependantProjects: " + directDependantProjects + + def dependantProjConfigs = directDependantProjects.collect { it.projectConfiguration } +println "#### configs: "+dependantProjConfigs + def dependantProjPublishArtifacts = dependantProjConfigs.collect { it.artifacts } +println "#### dependantProjPublishArtifacts: "+dependantProjPublishArtifacts + def files = dependantProjPublishArtifacts.collect { it.files.getAsPath() } +println "#### files: "+files + + directDependantProjects = directDependantProjects.collect { it.dependencyProject } + + def jars = directDependantProjects.collect { getProjJar it } + println "#### jars: " + jars + return jars +} +// ================================================================== + /* Configure subprojects */ subprojects { @@ -80,12 +247,15 @@ subprojects { apply plugin: 'java' apply plugin: "jacoco" ext.artifact = project.name - //group = 'org.apache.edgent' if (buildFile.isFile() && !buildFile.exists()) { configurations.create('default') return } + + assemble { // in configure phase... + recordProjectJar(project) + } if (["javax.websocket-client", "javax.websocket-server", "edgent.javax.websocket"].contains(project.name)) { archivesBaseName = "${project.name}" @@ -151,8 +321,12 @@ subprojects { attributes( 'Implementation-Title': "${-> baseName}", 'Implementation-Vendor': build_vendor, + // TODO inclusion of DSTAMP/TSTAMP results in regeneration + // of a jar when none of its contents/dependencies have changed. + // If possible use a canned DSTAMP/TSTAMP for non-"release" tasks + // to make the dev cycle more efficient at the expense of the TSTAMP. 'Implementation-Version': "${commithash}-${DSTAMP}-${TSTAMP}", - // TODO Class-Path attribute + 'Class-Path': mkManifestClassPath(project), ) } metaInf { @@ -167,49 +341,45 @@ subprojects { if(it.path == ":test:fvtiot" || it.path == ":providers:development") { dependsOn ":console:servlets" } + } + jar.doFirst { configure jarOptions } task copyJar(type: Copy) { description = "Copy subproject's assembled artifacts to target_dir (implicitly builds jars due to 'from jar')" - def projectGroup = "$project.group".replace("edgent.", "") - - if (["api", "providers", "runtime", "spi"].contains(projectGroup)) { - // println "copyJar(cfg) lib $project.group $projectGroup $project.name $jar.archiveName" - from jar - into "${rootProject.ext.target_java8_dir}/lib" - rename("$jar.archiveName", "$jar.baseName.$jar.extension") - } - else if (["samples"].contains(projectGroup)) { - // println "copyJar(cfg) samples $project.group $projectGroup $project.name $jar.archiveName" + + def relProjDirInTarget = getRelProjectDirInTargetDir(project, 'lib') + def absProjDirInTarget = "$target_java8_dir/$relProjDirInTarget" + + if (relProjDirInTarget != null) { from jar - into "${rootProject.ext.target_java8_dir}/$projectGroup/lib" + into absProjDirInTarget rename("$jar.archiveName", "$jar.baseName.$jar.extension") + } + def simpleProjectGroup = getSimpleProjectGroup project + + // Copy war when appropriate + if (project.path == ':console:servlets') { + doLast { + copy { + from war + into "${rootProject.ext.target_java8_dir}/$simpleProjectGroup/webapps" + } + } + } + + // Copy SRC when appropriate + if (simpleProjectGroup == 'samples') { //Copy Sample SRC to dist doLast { copy { from(sourceSets.main.allSource.srcDirs) { include '**/*.java' } - into "${rootProject.ext.target_java8_dir}/$projectGroup/src/$project.name/src/main/java/" + into "${rootProject.ext.target_java8_dir}/$simpleProjectGroup/src/$project.name/src/main/java/" } } } - else { - // println "copyJar(cfg) other $project.group $projectGroup $project.name $jar.archiveName" - from jar - into "${rootProject.ext.target_java8_dir}/$projectGroup/$project.name/lib" - rename("$jar.archiveName", "$jar.baseName.$jar.extension") - - // Copy console.war (should be more general but this works for now) - if (projectGroup == 'console' && project.name == 'servlets') { - doLast { - copy { - from war - into "${rootProject.ext.target_java8_dir}/$projectGroup/webapps" - } - } - } - } } task sourceJar(type: Jar) {