diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 03de150b2a..1c8cdf0e12 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -138,7 +138,7 @@ jobs: uses: gradle/actions/wrapper-validation@v5.0.2 - name: Test with Gradle Wrapper run: | - ./gradlew :jme3-screenshot-test:screenshotTest + ./gradlew :jme3-screenshot-tests:screenshotTest - name: Upload Test Reports uses: actions/upload-artifact@v7.0.0 if: always() @@ -241,7 +241,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest,windows-latest,macOS-latest] - jdk: [11, 17, 21] + jdk: [17, 21] include: - os: ubuntu-latest osName: linux @@ -252,8 +252,6 @@ jobs: - os: macOS-latest osName: mac deploy: false - - jdk: 11 - deploy: false - jdk: 17 deploy: false @@ -287,7 +285,7 @@ jobs: shell: bash run: | # Normal build plus ZIP distribution and merged javadoc - ./gradlew -PuseCommitHashAsVersionName=true -PskipPrebuildLibraries=true \ + ./gradlew -PuseCommitHashAsVersionName=true -PskipPrebuildLibraries=true -PbuildJavaDoc=true \ -x checkstyleMain -x checkstyleTest \ build createZipDistribution mergedJavadoc @@ -308,13 +306,13 @@ jobs: echo "SIGNING_KEY, SIGNING_PASSWORD" ./gradlew publishMavenPublicationToDistRepository \ - -PskipPrebuildLibraries=true -PuseCommitHashAsVersionName=true \ + -PskipPrebuildLibraries=true -PuseCommitHashAsVersionName=true -PbuildJavaDoc=true \ --console=plain --stacktrace else ./gradlew publishMavenPublicationToDistRepository \ -PsigningKey='${{ secrets.SIGNING_KEY }}' \ -PsigningPassword='${{ secrets.SIGNING_PASSWORD }}' \ - -PskipPrebuildLibraries=true -PuseCommitHashAsVersionName=true \ + -PskipPrebuildLibraries=true -PuseCommitHashAsVersionName=true -PbuildJavaDoc=true \ --console=plain --stacktrace fi @@ -493,6 +491,7 @@ jobs: -PsigningKey='${{ secrets.SIGNING_KEY }}' \ -PsigningPassword='${{ secrets.SIGNING_PASSWORD }}' \ -PuseCommitHashAsVersionName=true \ + -PbuildJavaDoc=true \ --console=plain --stacktrace fi @@ -556,6 +555,7 @@ jobs: -PsigningKey='${{ secrets.SIGNING_KEY }}' \ -PsigningPassword='${{ secrets.SIGNING_PASSWORD }}' \ -PuseCommitHashAsVersionName=true \ + -PbuildJavaDoc=true \ --console=plain --stacktrace .github/actions/tools/uploadToCentral.sh \ -p '${{ secrets.CENTRAL_PASSWORD }}' \ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c1cf2bbb68..511366b313 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -139,12 +139,14 @@ Run the Gradle wrapper: After a successful build, snapshot jars will be found in the "*/build/libs" subfolders. +The default build skips JavaDoc and source archives for speed; release and +publishing tasks build them explicitly. ### Related Gradle tasks You can install the Maven artifacts to your local repository: - + using Bash or PowerShell: `./gradlew install` - + using Windows Command Prompt: `.\gradlew install` + + using Bash or PowerShell: `./gradlew -PbuildJavaDoc=true install` + + using Windows Command Prompt: `.\gradlew -PbuildJavaDoc=true install` You can restore the project to a pristine state: + using Bash or PowerShell: `./gradlew clean` diff --git a/README.md b/README.md index 923eeb6480..1b24b1bab2 100644 --- a/README.md +++ b/README.md @@ -97,10 +97,12 @@ Read our [contribution guide](https://github.com/jMonkeyEngine/jmonkeyengine/blo After a successful build, fresh JARs will be found in "*/build/libs". +The default build skips JavaDoc and source archives for speed; release and +publishing tasks build them explicitly. You can install the JARs to your local Maven repository: -+ using Bash or Fish or PowerShell or Zsh: `./gradlew install` -+ using Windows Command Prompt: `.\gradlew install` ++ using Bash or Fish or PowerShell or Zsh: `./gradlew -PbuildJavaDoc=true install` ++ using Windows Command Prompt: `.\gradlew -PbuildJavaDoc=true install` You can run the "jme3-examples" app: + using Bash or Fish or PowerShell or Zsh: `./gradlew run` diff --git a/build.gradle b/build.gradle index 364a050846..7e66d886c4 100644 --- a/build.gradle +++ b/build.gradle @@ -13,6 +13,8 @@ buildscript { } import org.gradle.api.file.RelativePath +import java.nio.file.Files +import java.nio.file.StandardCopyOption // Set the license for IDEs that understand this ext.license = file("$rootDir/source-file-header-template.txt") @@ -25,7 +27,7 @@ allprojects { mavenCentral() google() } - tasks.withType(Jar) { + tasks.withType(Jar).configureEach { duplicatesStrategy = 'include' } } @@ -47,7 +49,7 @@ subprojects { toolVersion = libs.versions.spotbugs.get() } - tasks.withType(com.github.spotbugs.snom.SpotBugsTask ) { + tasks.withType(com.github.spotbugs.snom.SpotBugsTask).configureEach { reports { html.required = !project.hasProperty("xml-reports") xml.required = project.hasProperty("xml-reports") @@ -63,39 +65,57 @@ tasks.register('run') { defaultTasks 'run' +def fileSystemOperations = services.get(FileSystemOperations) +def libDistDir = layout.buildDirectory.dir('libDist') +def libDistArchives = subprojects.collectMany { subproject -> + if (subproject.hasProperty('mainClassName')) { + return [] + } + subproject.tasks.withType(Jar).matching { task -> + task.name == 'jar' || + task.name == 'sourcesJar' || + (buildJavaDoc == "true" && task.name == 'javadocJar') + }.collect { archiveTask -> + [ + projectName: subproject.name, + archiveFile: archiveTask.archiveFile, + archiveClassifier: archiveTask.archiveClassifier, + archiveExtension: archiveTask.archiveExtension, + ] + } +} + def libDist = tasks.register('libDist') { - dependsOn(subprojects.collect { it.tasks.named('build') }) + dependsOn(libDistArchives.collect { it.archiveFile }) description = 'Builds and copies the engine binaries, sources and javadoc to build/libDist' + inputs.files(libDistArchives.collect { it.archiveFile }) + outputs.dir(libDistDir) doLast { - File libFolder = mkdir("$buildDir/libDist/lib") - File sourceFolder = mkdir("$buildDir/libDist/sources") - File javadocFolder = mkdir("$buildDir/libDist/javadoc") - subprojects.each {project -> - if(!project.hasProperty('mainClassName')){ - project.tasks.withType(Jar).each {archiveTask -> - String classifier = archiveTask.archiveClassifier.get() - String ext = archiveTask.archiveExtension.get() - File archiveFile = archiveTask.archiveFile.get().asFile - if (classifier == "sources") { - copy { - from archiveFile - into sourceFolder - rename {project.name + '-' + classifier + '.' + ext} - } - } else if (classifier == "javadoc") { - copy { - from archiveFile - into javadocFolder - rename {project.name + '-' + classifier + '.' + ext} - } - } else{ - copy { - from archiveFile - into libFolder - rename {project.name + '.' + ext} - } - } + File libFolder = libDistDir.get().dir('lib').asFile + File sourceFolder = libDistDir.get().dir('sources').asFile + File javadocFolder = libDistDir.get().dir('javadoc').asFile + libDistArchives.each { archive -> + String classifier = archive.archiveClassifier.get() + String ext = archive.archiveExtension.get() + File archiveFile = archive.archiveFile.get().asFile + if (classifier == "sources") { + fileSystemOperations.copy { + from archiveFile + into sourceFolder + rename {archive.projectName + '-' + classifier + '.' + ext} + } + } else if (classifier == "javadoc") { + fileSystemOperations.copy { + from archiveFile + into javadocFolder + rename {archive.projectName + '-' + classifier + '.' + ext} + } + } else{ + fileSystemOperations.copy { + from archiveFile + into libFolder + rename {archive.projectName + '.' + ext} } } } @@ -146,6 +166,7 @@ def mergedJavadocSubprojects = [ ":jme3-terrain", ] tasks.register('mergedJavadoc', Javadoc) { + dependsOn mergedJavadocSubprojects.collect { project(it).tasks.named('classes') } description = 'Creates Javadoc from all the projects.' title = 'jMonkeyEngine3' destinationDir = file("dist/javadoc") @@ -157,7 +178,7 @@ tasks.register('mergedJavadoc', Javadoc) { options.overview = file("javadoc-overview.html") source = mergedJavadocSubprojects.collect { project(it).sourceSets.main.allJava } - classpath = files(mergedJavadocSubprojects.collect { project(it).sourceSets.main.compileClasspath }) + classpath = files(mergedJavadocSubprojects.collect { project(it).sourceSets.main.compileClasspath.files }) } def cleanMergedJavadoc = tasks.register('cleanMergedJavadoc', Delete) { @@ -197,37 +218,32 @@ gradle.rootProject.ext.set("usePrebuildNatives", buildNativeProjects!="true"); if (skipPrebuildLibraries != "true" && buildNativeProjects != "true") { File nativesSnapshotPropF = file('natives-snapshot.properties') + String prebuildNativesUrlTemplate = PREBUILD_NATIVES_URL if (nativesSnapshotPropF.exists()) { - def readNativesConfig = { - Properties nativesSnapshotProp = new Properties() - nativesSnapshotPropF.withInputStream { nativesSnapshotProp.load(it) } - - String nativesSnapshot = nativesSnapshotProp.getProperty("natives.snapshot") - if (!nativesSnapshot) { - throw new GradleException("Missing 'natives.snapshot' in ${nativesSnapshotPropF}") - } + Properties nativesSnapshotProp = new Properties() + nativesSnapshotPropF.withInputStream { nativesSnapshotProp.load(it) } - [ - snapshot: nativesSnapshot, - url: PREBUILD_NATIVES_URL.replace('${natives.snapshot}', nativesSnapshot), - zipFile: layout.buildDirectory.file("${nativesSnapshot}-natives.zip"), - nativeDir: layout.buildDirectory.dir("native"), - ] + String nativesSnapshot = nativesSnapshotProp.getProperty("natives.snapshot") + if (!nativesSnapshot) { + throw new GradleException("Missing 'natives.snapshot' in ${nativesSnapshotPropF}") } - def nativesZipFile = providers.provider { readNativesConfig().zipFile.get().asFile } + String nativesUrl = prebuildNativesUrlTemplate.replace('${natives.snapshot}', nativesSnapshot) + File nativesZipFile = layout.buildDirectory.file("${nativesSnapshot}-natives.zip").get().asFile def nativesPath = layout.buildDirectory.dir("native") def getNativesZipFile = tasks.register('getNativesZipFile') { + inputs.property('nativesUrl', nativesUrl) outputs.file(nativesZipFile) doFirst { - def nativesConfig = readNativesConfig() - File target = nativesConfig.zipFile.get().asFile - println("Use natives snapshot: ${nativesConfig.url}") - println("Download natives from ${nativesConfig.url} to ${target}") - target.getParentFile().mkdirs() - ant.get(src: nativesConfig.url, dest: target) + println("Use natives snapshot: ${nativesUrl}") + println("Download natives from ${nativesUrl} to ${nativesZipFile}") + nativesZipFile.getParentFile().mkdirs() + File tempFile = new File(nativesZipFile.parentFile, "${nativesZipFile.name}.part") + tempFile.delete() + ant.get(src: nativesUrl, dest: tempFile) + Files.move(tempFile.toPath(), nativesZipFile.toPath(), StandardCopyOption.REPLACE_EXISTING) } } @@ -235,7 +251,7 @@ if (skipPrebuildLibraries != "true" && buildNativeProjects != "true") { dependsOn(getNativesZipFile) into(nativesPath) from({ - zipTree(readNativesConfig().zipFile.get().asFile) + zipTree(nativesZipFile) }) { eachFile { details -> def segments = details.relativePath.segments diff --git a/common.gradle b/common.gradle index 554014ff80..f13e6ddd75 100644 --- a/common.gradle +++ b/common.gradle @@ -3,24 +3,52 @@ // apply plugin: 'java-library' -apply plugin: 'groovy' -apply plugin: 'maven-publish' -apply plugin: 'signing' -apply plugin: 'eclipse' -apply plugin: 'checkstyle' - -eclipse.jdt.file.withProperties { props -> - props.setProperty "org.eclipse.jdt.core.circularClasspath", "warning" -} group = 'org.jmonkeyengine' version = jmeFullVersion +def requestedTasks = gradle.startParameter.taskNames +def taskRequested = { String taskName -> + requestedTasks.any { requested -> + requested == taskName || requested.endsWith(":${taskName}") + } +} +def taskNameContains = { String fragment -> + requestedTasks.any { requested -> + requested.toLowerCase(Locale.ROOT).contains(fragment.toLowerCase(Locale.ROOT)) + } +} +def publishRequested = taskNameContains('publish') || taskRequested('install') +def checkstyleRequested = taskNameContains('checkstyle') +def eclipseRequested = taskNameContains('eclipse') +def groovySourcePresent = project.name == 'jme3-core' + +if (groovySourcePresent) { + apply plugin: 'groovy' +} + +if (publishRequested) { + apply plugin: 'maven-publish' + apply plugin: 'signing' +} + +if (eclipseRequested) { + apply plugin: 'eclipse' + + eclipse.jdt.file.withProperties { props -> + props.setProperty "org.eclipse.jdt.core.circularClasspath", "warning" + } +} + +if (checkstyleRequested) { + apply plugin: 'checkstyle' +} + java { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } -tasks.withType(JavaCompile) { // compile-time options: +tasks.withType(JavaCompile).configureEach { // compile-time options: //options.compilerArgs << '-Xlint:deprecation' // to show deprecation warnings options.compilerArgs << '-Xlint:unchecked' options.encoding = 'UTF-8' @@ -40,7 +68,9 @@ dependencies { // Adding dependencies here will add the dependencies to each subproject. testImplementation libs.junit4 testImplementation libs.mokito.core - testImplementation libs.groovy.test + if (groovySourcePresent) { + testImplementation libs.groovy.test + } } // Uncomment if you want to see the status of every test that is run and @@ -62,7 +92,7 @@ jar { } } -javadoc { +tasks.named('javadoc', Javadoc) { failOnError = false options.memberLevel = org.gradle.external.javadoc.JavadocMemberLevel.PROTECTED options.docTitle = "jMonkeyEngine ${jmeFullVersion} ${project.name} Javadoc" @@ -84,14 +114,18 @@ test { } } -task sourcesJar(type: Jar, dependsOn: classes, description: 'Creates a jar from the source files.') { +def sourcesJar = tasks.register('sourcesJar', Jar) { + dependsOn classes + description = 'Creates a jar from the source files.' archiveClassifier = 'sources' from sourceSets*.allSource } -task javadocJar(type: Jar, dependsOn: javadoc, description: 'Creates a jar from the javadoc files.') { +def javadocJar = tasks.register('javadocJar', Jar) { + dependsOn javadoc + description = 'Creates a jar from the javadoc files.' archiveClassifier = 'javadoc' - from javadoc.destinationDir + from tasks.named('javadoc', Javadoc).map { it.destinationDir } } ext.pomConfig = { @@ -119,118 +153,117 @@ ext.pomConfig = { } } -artifacts { - archives jar - archives sourcesJar - if (buildJavaDoc == "true") { - archives javadocJar - } -} - -publishing { - publications { - maven(MavenPublication) { - artifact javadocJar - artifact sourcesJar - from components.java - pom { - description = POM_DESCRIPTION - developers { - developer { - id = 'jMonkeyEngine' - name = 'jMonkeyEngine Team' - } +if (publishRequested) { + publishing { + publications { + maven(MavenPublication) { + artifact sourcesJar + if (buildJavaDoc == "true") { + artifact javadocJar } - inceptionYear = POM_INCEPTION_YEAR - licenses { - license { - distribution = POM_LICENSE_DISTRIBUTION - name = POM_LICENSE_NAME - url = POM_LICENSE_URL + from components.java + pom { + description = POM_DESCRIPTION + developers { + developer { + id = 'jMonkeyEngine' + name = 'jMonkeyEngine Team' + } } + inceptionYear = POM_INCEPTION_YEAR + licenses { + license { + distribution = POM_LICENSE_DISTRIBUTION + name = POM_LICENSE_NAME + url = POM_LICENSE_URL + } + } + name = POM_NAME + scm { + connection = POM_SCM_CONNECTION + developerConnection = POM_SCM_DEVELOPER_CONNECTION + url = POM_SCM_URL + } + url = POM_URL } - name = POM_NAME - scm { - connection = POM_SCM_CONNECTION - developerConnection = POM_SCM_DEVELOPER_CONNECTION - url = POM_SCM_URL - } - url = POM_URL + version = project.version } - version = project.version } - } - repositories { - maven { - name = 'Dist' - url = gradle.rootProject.projectDir.absolutePath + '/dist/maven' - } + repositories { + maven { + name = 'Dist' + url = gradle.rootProject.projectDir.absolutePath + '/dist/maven' + } - // Uploading to Sonatype relies on the existence of 2 properties - // (centralUsername and centralPassword) - // which should be set using -P options on the command line. + // Uploading to Sonatype relies on the existence of 2 properties + // (centralUsername and centralPassword) + // which should be set using -P options on the command line. - maven { - // for uploading release builds to the default repo in Sonatype's OSSRH staging area - credentials { - username = gradle.rootProject.hasProperty('centralUsername') ? centralUsername : 'Unknown user' - password = gradle.rootProject.hasProperty('centralPassword') ? centralPassword : 'Unknown password' + maven { + // for uploading release builds to the default repo in Sonatype's OSSRH staging area + credentials { + username = gradle.rootProject.hasProperty('centralUsername') ? centralUsername : 'Unknown user' + password = gradle.rootProject.hasProperty('centralPassword') ? centralPassword : 'Unknown password' + } + name = 'Central' + url = 'https://ossrh-staging-api.central.sonatype.com/service/local/staging/deploy/maven2/' } - name = 'Central' - url = 'https://ossrh-staging-api.central.sonatype.com/service/local/staging/deploy/maven2/' - } - maven { - // for uploading snapshot builds to Sonatype's maven-snapshots repo - credentials { - username = gradle.rootProject.hasProperty('centralUsername') ? centralUsername : 'Unknown user' - password = gradle.rootProject.hasProperty('centralPassword') ? centralPassword : 'Unknown password' + maven { + // for uploading snapshot builds to Sonatype's maven-snapshots repo + credentials { + username = gradle.rootProject.hasProperty('centralUsername') ? centralUsername : 'Unknown user' + password = gradle.rootProject.hasProperty('centralPassword') ? centralPassword : 'Unknown password' + } + name = 'SNAPSHOT' + url = 'https://central.sonatype.com/repository/maven-snapshots/' } - name = 'SNAPSHOT' - url = 'https://central.sonatype.com/repository/maven-snapshots/' } } -} -publishToMavenLocal.doLast { - println 'published ' + project.getName() + "-${jmeFullVersion} to mavenLocal" -} -task('install') { - dependsOn 'publishToMavenLocal' -} + tasks.named('publishToMavenLocal') { + doLast { + println 'published ' + project.getName() + "-${jmeFullVersion} to mavenLocal" + } + } + tasks.register('install') { + dependsOn 'publishToMavenLocal' + } -signing { - def signingKey = gradle.rootProject.findProperty('signingKey') - def signingPassword = gradle.rootProject.findProperty('signingPassword') - useInMemoryPgpKeys(signingKey, signingPassword) + signing { + def signingKey = gradle.rootProject.findProperty('signingKey') + def signingPassword = gradle.rootProject.findProperty('signingPassword') + useInMemoryPgpKeys(signingKey, signingPassword) - sign configurations.archives - sign publishing.publications.maven -} -tasks.withType(Sign) { - onlyIf { gradle.rootProject.hasProperty('signingKey') } + sign publishing.publications.maven + } + tasks.withType(Sign).configureEach { + onlyIf { gradle.rootProject.hasProperty('signingKey') } + } } -def checkstyleSupported = JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_21) +if (checkstyleRequested) { + def checkstyleSupported = JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_21) -checkstyle { - toolVersion = libs.versions.checkstyle.get() - configFile = file("${gradle.rootProject.rootDir}/config/checkstyle/checkstyle.xml") -} + checkstyle { + toolVersion = libs.versions.checkstyle.get() + configFile = file("${gradle.rootProject.rootDir}/config/checkstyle/checkstyle.xml") + } -checkstyleMain { - source ='src/main/java' -} + checkstyleMain { + source ='src/main/java' + } -checkstyleTest { - source ='src/test/java' -} + checkstyleTest { + source ='src/test/java' + } -tasks.withType(Checkstyle) { - enabled = checkstyleSupported - reports { - xml.required.set(false) - html.required.set(true) + tasks.withType(Checkstyle).configureEach { + enabled = checkstyleSupported + reports { + xml.required.set(false) + html.required.set(true) + } + include("**/com/jme3/renderer/**/*.java") } - include("**/com/jme3/renderer/**/*.java") } diff --git a/gradle.properties b/gradle.properties index d924be823d..081ce83cc7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,8 +12,13 @@ useCommitHashAsVersionName = false # generated version. includeBranchInVersion = false -# specify if JavaDoc should be built -buildJavaDoc = true +# specify if JavaDoc should be built +buildJavaDoc = false + +# Gradle performance defaults +org.gradle.parallel=true +org.gradle.caching=true +org.gradle.configuration-cache=true # specify if SDK and Native libraries get built buildNativeProjects = false diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 1b33c55baa..d997cfc60f 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index aaaabb3cb9..c61a118f7d 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 23d15a9367..739907dfd1 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -57,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/2d6327017519d23b96af35865dc997fcb544fb40/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -114,7 +114,6 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH="\\\"\\\"" # Determine the Java command to use to start the JVM. @@ -172,7 +171,6 @@ fi # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) @@ -212,7 +210,6 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" diff --git a/gradlew.bat b/gradlew.bat index 5eed7ee845..e509b2dd8f 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -70,11 +70,10 @@ goto fail :execute @rem Setup the command line -set CLASSPATH= @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell diff --git a/jme3-android-native/openalsoft.gradle b/jme3-android-native/openalsoft.gradle index 0a14d4b429..bf32b926bd 100644 --- a/jme3-android-native/openalsoft.gradle +++ b/jme3-android-native/openalsoft.gradle @@ -92,6 +92,9 @@ def openalAbis = [ "x86", "x86_64" ] +def openalCmakeBuildJobs = providers.gradleProperty('openalCmakeBuildJobs') + .map { it as int } + .orElse(Math.max(1, Runtime.runtime.availableProcessors().intdiv(openalAbis.size()))) // 2) for each ABI, register a configure/build pair openalAbis.each { abi -> @@ -135,7 +138,8 @@ openalAbis.each { abi -> commandLine = [ "cmake", "--build", "cmake-build-${abi}", - "--config", "Release" + "--config", "Release", + "--parallel", openalCmakeBuildJobs.get() as String ] } } diff --git a/jme3-examples/build.gradle b/jme3-examples/build.gradle index b3468883cc..c58f25e040 100644 --- a/jme3-examples/build.gradle +++ b/jme3-examples/build.gradle @@ -1,10 +1,26 @@ -ext.mainClassName = 'jme3test.TestChooser' +def examplesMainClassName = 'jme3test.TestChooser' +ext.mainClassName = examplesMainClassName def androidProject = project(':jme3-android') def androidNativeProject = project(':jme3-android-native') +def androidProjectName = androidProject.name +def androidNativeProjectName = androidNativeProject.name +def fileSystemOperations = services.get(FileSystemOperations) +def compileClasspath = configurations.compileClasspath +def compileClasspathArtifacts = providers.provider { + compileClasspath.resolvedConfiguration.resolvedArtifacts.collect { artifact -> + [ + file: artifact.file, + fileName: artifact.classifier != null ? + "${artifact.name}-${artifact.classifier}.${artifact.extension}" : + "${artifact.name}.${artifact.extension}", + ] + } +} -task run(dependsOn: 'build', type:JavaExec) { - mainClass = mainClassName +tasks.register('run', JavaExec) { + dependsOn sourceSets.main.runtimeClasspath + mainClass = examplesMainClassName classpath = sourceSets.main.runtimeClasspath if (System.properties['java.util.logging.config.file'] != null) { @@ -46,47 +62,50 @@ jar.doFirst{ // 'Implementation-Title' : appName, // 'Implementation-Version' : version, // 'Implementation-Vendor' : vendor, - 'Main-Class' : getProperty('mainClassName'), + 'Main-Class' : examplesMainClassName, // Add dependencies to manifest, remove version - 'Class-Path' : configurations.compileClasspath.resolvedConfiguration.resolvedArtifacts.collect { - 'lib/' + - it.name + - (it.classifier != null ? '-' + it.classifier : '') + - '.' + it.extension }.join(' ') + 'Class-Path' : compileClasspathArtifacts.get().collect { 'lib/' + it.fileName }.join(' ') ) } } -task dist (dependsOn: ['build', ':jme3-android:jar', ':jme3-android-native:jar']) { +tasks.register('dist') { + dependsOn 'build', ':jme3-android:jar', ':jme3-android-native:jar' + def examplesJar = tasks.named('jar', Jar).flatMap { it.archiveFile } + def androidJar = androidProject.tasks.named('jar', Jar).flatMap { it.archiveFile } + def androidNativeJar = androidNativeProject.tasks.named('jar', Jar).flatMap { it.archiveFile } + def distDir = rootProject.layout.projectDirectory.dir('dist') + + inputs.files(compileClasspathArtifacts.map { artifacts -> artifacts.collect { it.file } }) + inputs.files(examplesJar, androidJar, androidNativeJar) + outputs.dir(distDir) + doLast { // Copy all dependencies to ../dist/lib, remove versions from jar files - configurations.compileClasspath.resolvedConfiguration.resolvedArtifacts.each { artifact -> - copy { + compileClasspathArtifacts.get().each { artifact -> + fileSystemOperations.copy { + duplicatesStrategy = DuplicatesStrategy.INCLUDE from artifact.file - into '../dist/lib' - if(artifact.classifier != null){ - rename { "${artifact.name}-${artifact.classifier}.${artifact.extension}" } - } else{ - rename { "${artifact.name}.${artifact.extension}" } - } + into distDir.dir('lib') + rename { artifact.fileName } } } - copy { - from tasks.named('jar').flatMap { it.archiveFile } - into '../dist' + fileSystemOperations.copy { + from examplesJar + into distDir rename { "jMonkeyEngine3.jar" } } // Copy android packages, remove version - copy { - from androidProject.tasks.named('jar').flatMap { it.archiveFile } - into '../dist/opt/android' - rename { androidProject.name + ".jar" } + fileSystemOperations.copy { + from androidJar + into distDir.dir('opt/android') + rename { androidProjectName + ".jar" } } - copy { - from androidNativeProject.tasks.named('jar').flatMap { it.archiveFile } - into '../dist/opt/android' - rename { androidNativeProject.name + ".jar" } + fileSystemOperations.copy { + from androidNativeJar + into distDir.dir('opt/android') + rename { androidNativeProjectName + ".jar" } } } } diff --git a/jme3-screenshot-tests/build.gradle b/jme3-screenshot-tests/build.gradle index fdc8b92be5..2d892ae089 100644 --- a/jme3-screenshot-tests/build.gradle +++ b/jme3-screenshot-tests/build.gradle @@ -16,7 +16,8 @@ dependencies { implementation 'com.aventstack:extentreports:5.1.2' implementation platform('org.junit:junit-bom:5.9.1') - implementation 'org.junit.jupiter:junit-jupiter-api' + implementation 'org.junit.jupiter:junit-jupiter' + testRuntimeOnly 'org.junit.platform:junit-platform-launcher' testRuntimeOnly project(':jme3-testdata') } diff --git a/version.gradle b/version.gradle index fbed055bf9..50a60f9c74 100644 --- a/version.gradle +++ b/version.gradle @@ -1,15 +1,5 @@ import java.text.SimpleDateFormat -import org.ajoberstar.grgit.* - -buildscript { - repositories { - mavenCentral() - } - dependencies { - classpath libs.gradle.git - } -} ext { jmeRevision = 0 @@ -22,8 +12,18 @@ ext { jmeVersionTag="SNAPSHOT" } -task configureVersionInfo { - try { +def gitOutput = { List args -> + def output = providers.exec { + commandLine(['git'] + args) + ignoreExitValue = true + } + if (output.result.get().exitValue == 0) { + return output.standardOutput.asText.get().trim() + } + return "" +} + +try { // Users can configure behavior by setting properties on the command // line: // @@ -39,33 +39,21 @@ task configureVersionInfo { // Set to true if a non-master branch name should be included in the automatically // generated version. - def grgit = Grgit.open(project.file('.')) - def head = grgit.head() - jmeRevision = grgit.log(includes: [head]).size() - jmeGitHash = head.id - jmeShortGitHash = head.abbreviatedId - jmeBranchName = grgit.branch.current.name + jmeRevision = gitOutput(['rev-list', '--count', 'HEAD']) ?: 0 + jmeGitHash = gitOutput(['rev-parse', 'HEAD']) + jmeShortGitHash = gitOutput(['rev-parse', '--short=7', 'HEAD']) + jmeBranchName = gitOutput(['branch', '--show-current']) ?: gitOutput(['rev-parse', '--abbrev-ref', 'HEAD']) // This code will find an exact-match tag if the current // commit is the same as the tag commit. - jmeGitTag = grgit.tag.list().find { it.commit == head } + jmeGitTag = gitOutput(['describe', '--tags', '--exact-match', 'HEAD']) def latestTag; if( jmeGitTag ) { - // Just use the name. We keep jmeGitTag separate because there - // is some logic that wants to know if this specific commit has - // a tag versus 'whatever tag we are a child of'... which is what - // 'latestTag' will be. - jmeGitTag = jmeGitTag.name latestTag = jmeGitTag; } else { - // Use describe to find the most recent tag. Unfortunately, - // in this version of grgit, we don't have the 'always' options - // so we can't make as many assumptions about the format of the - // string. - // If the commit is an exact match then it will return just the - // tag name... else it will be tagName-commitCount-abbreviatedId - // We'll use some groovy regex magic to get the tag either way. - def describe = grgit.describe() + // If the commit is an exact match then this returns just the tag + // name, else it returns tagName-commitCount-abbreviatedId. + def describe = gitOutput(['describe', '--tags', '--abbrev=7', 'HEAD']) def fullDescribe = (describe =~/(.*?)-(\d+)-g$jmeShortGitHash/) latestTag = fullDescribe ? fullDescribe[0][1] : describe println "Latest tag:" + latestTag @@ -137,9 +125,8 @@ task configureVersionInfo { println("Build Suffix: ${jmeVersionTag}") println("Build Version: ${jmeFullVersion}") - } catch (ex) { - // Failed to get repo info - logger.warn("Failed to get repository info: " + ex.message + ". " + \ - "Only partial build info will be generated.") - } +} catch (ex) { + // Failed to get repo info + logger.warn("Failed to get repository info: " + ex.message + ". " + \ + "Only partial build info will be generated.") }