fix handling of aggregator-only projects, add "reports" Don't assemble jars or anything else for aggregator-only projects via omitting applying the 'java' plugin to them. That then avoids their undesired jars being added to the target-dir and release.tgz.
Also - remove unneeded subprojects*.jar dependency in aggregateJavadoc - add "reports" task - remove "dependsOn test" from report tasks (reports shouldn't induce running tests) - Update DEVELOPMENT.md with gradle info - tweak jococoTestReport so "test reports" works - make 'assemble' also update target_dir - make root 'build' be like "all test reports" - tweak 'copyJar' so sample src copy works with all the changes TODO tgt_dir and tgz still missing console.war Project: http://git-wip-us.apache.org/repos/asf/incubator-edgent/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-edgent/commit/1a0f6783 Tree: http://git-wip-us.apache.org/repos/asf/incubator-edgent/tree/1a0f6783 Diff: http://git-wip-us.apache.org/repos/asf/incubator-edgent/diff/1a0f6783 Branch: refs/heads/master Commit: 1a0f6783669adc58efa7eae46e413f27214abfad Parents: efaf223 Author: Dale LaBossiere <dlab...@us.ibm.com> Authored: Thu Aug 11 16:23:35 2016 -0400 Committer: Dale LaBossiere <dlab...@us.ibm.com> Committed: Thu Aug 11 16:23:35 2016 -0400 ---------------------------------------------------------------------- DEVELOPMENT.md | 35 ++++++++++++ build.gradle | 147 +++++++++++++++++++++++++++++++++++++-------------- settings.gradle | 4 ++ 3 files changed, 146 insertions(+), 40 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-edgent/blob/1a0f6783/DEVELOPMENT.md ---------------------------------------------------------------------- diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index f53ea9f..cdae879 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -101,6 +101,41 @@ Running the reports target produces two reports: * `reports/junit/index.html` - JUnit test report * `reports/coverage/index.html` - Code coverage report. +### [WIP] Building With Gradle + +Work is ongoing to replace the Ant based build system with a Gradle based one +[EDGENT-139]. Delivered functionality is expected to work though is not yet +be complete. + +**TODO: The primary build process is using Gradle, any pull request is expected to +maintain the build success of `clean, all, test`.** + +The Gradle wrapper `edgent/{gradlew,gradlew.bat}` should be used to ensure an appropriate +version of Gradle is used. e.g. `$ ./gradlew clean all test reports` + +The top-level Gradle file is `edgent/build.gradle` and contains several +unique tasks: + +* `all` (default) : Build all code and Javadoc into `build\distributions`. The build will fail on any code error or Javadoc warning or error. +* `build` : essentially like "all test reports" +* `clean` : Clean the project +* `test` : Run the JUnit tests, if any test fails the test run stops. + * use a project test task and optionally the `--tests` option to run a subset of the tests: + * `./gradlew <project>:test` + * `./gradlew <project>:test --tests '*.SomeTest'` + * `./gradlew <project>:test --tests '*.SomeTest.someMethod'` +* `reports` : Generate JUnit and Code Coverage reports in `build\distributions\reports`. Use after executing the `test` target. + * `reports\tests\overview-summary.html` - JUnit test report + * `reports\coverage\index.html` - Code coverage report +* `release` : Build a release bundle in `build/release-edgent`, **TODO: that includes subsets of the Edgent jars that run on Java 7 (`build/distributions/java7`) and Android (`build/distributions/android`)**. + +The build process has been tested on Linux and MacOSX. + +To build on Windows probably needs some changes, please get involved and contribute them! + +**TODO: Continuous Integration with Gradle** + + ### Code Layout The code is broken into a number of projects and modules within those projects defined by directories under `edgent`. http://git-wip-us.apache.org/repos/asf/incubator-edgent/blob/1a0f6783/build.gradle ---------------------------------------------------------------------- diff --git a/build.gradle b/build.gradle index 571b12a..aa4f924 100644 --- a/build.gradle +++ b/build.gradle @@ -18,7 +18,6 @@ defaultTasks 'all' allprojects { apply plugin: 'idea' apply plugin: 'eclipse' - apply plugin: 'java' repositories { mavenCentral() @@ -28,6 +27,8 @@ allprojects { } } +apply plugin: 'java' + ext { commithash_error = '' commithash = { @@ -51,11 +52,28 @@ ext { target_docs_dir = "${ext.target_dir}/docs" target_javadoc_dir = "${ext.target_docs_dir}/javadoc" target_report_dir = "${ext.target_dir}/reports" + + aggregatorOnlyProjects = [ + ':analytics', ':api', ':apps', + ':connectors', ':console', ':providers', + ':runtime', ':samples', ':spi', + ':test', ':utils' + ] + + filteredSubprojects = subprojects*.findAll { + project -> !aggregatorOnlyProjects.contains(project.path) + } } /* Configure subprojects */ subprojects { + // ignore aggregator only projects so we don't assemble empty jars, etc for them. + if (aggregatorOnlyProjects.contains(project.path)) { + return + } + + apply plugin: 'java' apply plugin: "jacoco" if (buildFile.isFile() && !buildFile.exists()) { @@ -104,6 +122,9 @@ subprojects { } test { + // TODO fix this - this dependency handling shouldn't occur here, + // rather :console:server should dependOn :console:servlets + // (really the server doesn't exist w/o the servlets) if(it.path == ":test:fvtiot" || it.path == ":providers:development") { dependsOn ":console:servlets" } @@ -145,32 +166,41 @@ subprojects { } 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" + into "${rootProject.ext.target_java8_dir}/lib" rename("$jar.archiveName", "$jar.baseName.$jar.extension") - } else if (["samples"].contains(projectGroup)) { + } + else if (["samples"].contains(projectGroup)) { + // println "copyJar(cfg) samples $project.group $projectGroup $project.name $jar.archiveName" from jar - into "${rootProject.ext.target_java8_dir}/" + projectGroup + "/lib" + into "${rootProject.ext.target_java8_dir}/$projectGroup/lib" rename("$jar.archiveName", "$jar.baseName.$jar.extension") //Copy Sample SRC to dist - copy { - into "${rootProject.ext.target_java8_dir}/" + projectGroup + "/src/$project.name/src/main/java/" - from(sourceSets.main.allSource.srcDirs) { - include '**/*.java' + doLast { + copy { + from(sourceSets.main.allSource.srcDirs) { + include '**/*.java' + } + into "${rootProject.ext.target_java8_dir}/$projectGroup/src/$project.name/src/main/java/" } } - } else { + } + else { + // println "copyJar(cfg) other $project.group $projectGroup $project.name $jar.archiveName" from jar - into "${rootProject.ext.target_java8_dir}/" + projectGroup + "/$project.name".replaceAll(":", "/") + "/lib" + into "${rootProject.ext.target_java8_dir}/$projectGroup/$project.name/lib" rename("$jar.archiveName", "$jar.baseName.$jar.extension") } } - - copyJar.dependsOn assemble + + // assemble: inject updating target_dir + assemble.finalizedBy copyJar } task copyScripts(type: Copy) { @@ -192,7 +222,7 @@ dependencies { } task createJunitReport << { - description = 'Generates a Junit report from all subprojects' + description = "Generates a Junit report from all subprojects (use after 'test')" ant.taskdef(name: 'junitreport', classname: 'org.apache.tools.ant.taskdefs.optional.junit.XMLResultAggregator', @@ -201,15 +231,13 @@ task createJunitReport << { fileset(dir: './') { include(name: '**/test-results/TEST-*.xml') } - report(format: 'frames', todir: "${target_report_dir}/junit") + report(format: 'frames', todir: "${target_report_dir}/tests") } ant.move(file: "TESTS-TestSuites.xml", tofile: "${target_report_dir}/TESTS-TestSuites.xml") } -build.finalizedBy createJunitReport task jacocoTestReport << { - - description = 'Generates a coverage report from all subprojects' + description = "Generates a coverage report from all subprojects (use after 'test')" def libDir = new File("${target_java8_dir}", "lib") def utilsDir = new File("${target_java8_dir}", "utils") @@ -241,10 +269,18 @@ task jacocoTestReport << { executionData.addToAntBuilder(ant, 'resources') } + // the 'test' task directly uses the built class files + // (test doesn't assemble jars nor populate target_dir with them) + jococoClassfilesFromJars = false; + structure(name: project.name) { group(name: "Edgent API") { classfiles { - fileset(dir: "${target_java8_dir}/lib", includes: "edgent.api.*.jar") + if (jococoClassfilesFromJars) { + fileset(dir: "${target_java8_dir}/lib", includes: "edgent.api.*.jar") + } else { + fileset(dir: "api", includes: "**/*.class") + } } sourcefiles { fileset(dir: "./api/function/src/main/java", includes: "**/*.java") @@ -256,7 +292,11 @@ task jacocoTestReport << { } group(name: "Edgent SPI") { classfiles { - fileset(dir: "${target_java8_dir}/lib", includes: "edgent.spi.*.jar") + if (jococoClassfilesFromJars) { + fileset(dir: "${target_java8_dir}/lib", includes: "edgent.spi.*.jar") + } else { + fileset(dir: "spi", includes: "**/*.class") + } } sourcefiles { fileset(dir: "./spi/graph/src/main/java", includes: "**/*.java") @@ -265,7 +305,11 @@ task jacocoTestReport << { } group(name: "Edgent Runtime") { classfiles { - fileset(dir: "${target_java8_dir}/lib", includes: "edgent.runtime.*.jar") + if (jococoClassfilesFromJars) { + fileset(dir: "${target_java8_dir}/lib", includes: "edgent.runtime.*.jar") + } else { + fileset(dir: "runtime", includes: "**/*.class") + } } sourcefiles { fileset(dir: "./runtime/etiao/src/main/java", includes: "**/*.java") @@ -274,7 +318,11 @@ task jacocoTestReport << { } group(name: "Edgent Utilities") { classfiles { - fileset(dir: "${target_java8_dir}/utils", includes: "**/edgent.utils.*.jar") + if (jococoClassfilesFromJars) { + fileset(dir: "${target_java8_dir}/utils", includes: "**/edgent.utils.*.jar") + } else { + fileset(dir: "utils", includes: "**/*.class") + } } sourcefiles { fileset(dir: "./utils/metrics/src/main/java", includes: "**/*.java") @@ -283,7 +331,11 @@ task jacocoTestReport << { } group(name: "Edgent Connectors") { classfiles { - fileset(dir: "${target_java8_dir}/connectors", includes: "**/edgent.connectors.*.jar") + if (jococoClassfilesFromJars) { + fileset(dir: "${target_java8_dir}/connectors", includes: "**/edgent.connectors.*.jar") + } else { + fileset(dir: "connectors", includes: "**/*.class") + } } sourcefiles { fileset(dir: "./connectors/common/src/main/java", includes: "**/*.java") @@ -302,7 +354,11 @@ task jacocoTestReport << { } group(name: "Edgent Providers") { classfiles { - fileset(dir: "${target_java8_dir}/lib", includes: "edgent.providers.*.jar") + if (jococoClassfilesFromJars) { + fileset(dir: "${target_java8_dir}/lib", includes: "edgent.providers.*.jar") + } else { + fileset(dir: "providers", includes: "**/*.class") + } } sourcefiles { fileset(dir: "./providers/direct/src/main/java", includes: "**/*.java") @@ -311,7 +367,11 @@ task jacocoTestReport << { } group(name: "Edgent Analytics") { classfiles { - fileset(dir: "${target_java8_dir}/analytics", includes: "**/edgent.analytics.*.jar") + if (jococoClassfilesFromJars) { + fileset(dir: "${target_java8_dir}/analytics", includes: "**/edgent.analytics.*.jar") + } else { + fileset(dir: "analytics", includes: "**/*.class") + } } sourcefiles { fileset(dir: "./analytics/math3/src/main/java", includes: "**/*.java") @@ -320,7 +380,11 @@ task jacocoTestReport << { } group(name: "Edgent Console") { classfiles { - fileset(dir: "${target_java8_dir}/console", includes: "**/edgent.console.*.jar") + if (jococoClassfilesFromJars) { + fileset(dir: "${target_java8_dir}/console", includes: "**/edgent.console.*.jar") + } else { + fileset(dir: "console", includes: "**/*.class") + } } sourcefiles { fileset(dir: "./console/server/src/main/java", includes: "**/*.java") @@ -332,13 +396,9 @@ task jacocoTestReport << { xml(destfile: "${target_report_dir}/coverage/jacoco-sessions.xml") } } -build.finalizedBy jacocoTestReport -// jacocoTestReport.dependsOn subprojects*.test, subprojects*.copyJar -jacocoTestReport.dependsOn subprojects*.test task aggregateJavadoc(type: Javadoc) { description = 'Create all javadoc into target_dir/docs/javadoc' - dependsOn(subprojects*.jar) // why is this needed? destinationDir file("$rootProject.ext.target_javadoc_dir") options.addStringOption('Xdoclint:none', '-quiet') configure(options) { @@ -381,10 +441,6 @@ task aggregateJavadoc(type: Javadoc) { } } -task copyJars(dependsOn: subprojects*.copyJar) { - description = 'copyJar aggregator' -} - task addVersionDotTxt { description = 'Add version.txt in target_dir' doLast { @@ -408,7 +464,7 @@ task mkTargetDir << { task addMiscDistFiles { description = 'Add misc things to target_dir' - dependsOn 'mkTargetDir', 'addVersionDotTxt' + dependsOn mkTargetDir, addVersionDotTxt addVersionDotTxt.mustRunAfter mkTargetDir doLast { copy { from 'LICENSE'; into target_dir } @@ -436,24 +492,35 @@ task releaseTarGz(type: Tar) { } task all { - description = 'Assemble distribution artifacts and populate the target_dir with jars, doc, etc.' - dependsOn('copyJars', 'copyScripts', 'aggregateJavadoc') + description = "Assemble distribution artifacts and populate the target_dir with jars, doc, etc. Like 'build' w/o 'test'" + dependsOn filteredSubprojects*.assemble, copyScripts, aggregateJavadoc } task cleanAll { - description = 'clean aggregator' // e.g., release dependsOn clean only does top-level clean - dependsOn 'clean' // top-level clean too - dependsOn subprojects*.clean + description = 'clean aggregator' // "release dependsOn clean" only does top-level clean + dependsOn clean, filteredSubprojects*.clean } task release { description = 'Assemble distribution artifacts, populate target_dir, and create a release tgz' - dependsOn('cleanAll', 'addMiscDistFiles', 'all', 'releaseTarGz') + dependsOn cleanAll, addMiscDistFiles, all, releaseTarGz addMiscDistFiles.mustRunAfter cleanAll all.mustRunAfter addMiscDistFiles releaseTarGz.mustRunAfter all } +task reports { + description = "Generate JUnit and Coverage reports of prior test run. Use after 'test'" + dependsOn createJunitReport, jacocoTestReport +} + +// build: inject test report generation and javadoc generation (for early problem detection) +// make 'build' like "all test reports" +build { + dependsOn filteredSubprojects*.build, aggregateJavadoc, copyScripts + finalizedBy reports // after build's test task +} + task wrapper(type: Wrapper) { jarFile = rootProject.file('.gradle-wrapper/gradle-wrapper.jar') } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-edgent/blob/1a0f6783/settings.gradle ---------------------------------------------------------------------- diff --git a/settings.gradle b/settings.gradle index 36fe2d8..64d96cc 100644 --- a/settings.gradle +++ b/settings.gradle @@ -11,6 +11,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +// N.B. if you add a subproject to a new 'aggregator only' project +// adjust the 'aggregatorOnlyProjects' list in build.gradle + include 'api:function' include 'api:execution' include 'api:window'