From 46d593832a1dc76ade73d108e371b4bddd1df5fb Mon Sep 17 00:00:00 2001 From: Davis Rollman Date: Tue, 14 Apr 2026 12:22:20 -0400 Subject: [PATCH 1/3] Use git CLI for version metadata --- version.gradle | 66 +++++++++++++++++++++----------------------------- 1 file changed, 27 insertions(+), 39 deletions(-) diff --git a/version.gradle b/version.gradle index fbed055bf9..c11edf9c08 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,22 @@ 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 + def revisionOutput = gitOutput(['rev-list', '--count', 'HEAD']) + jmeRevision = revisionOutput ? revisionOutput.toInteger() : 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 @@ -73,9 +62,9 @@ task configureVersionInfo { // We could enhance this with some more regex if we wanted to sanity // check that it was formatted like our versions. - def tagVersion = (latestTag =~/v?(.*)/)[0][1]; + def tagVersion = latestTag ? (latestTag =~/v?(.*)/)[0][1] : jmeVersion; // If the branch is not master then use the tag. - if( jmeBranchName != "master" ) { + if( jmeBranchName != "master" && latestTag ) { jmeVersion = tagVersion } @@ -137,9 +126,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.") } From 794f427194fe28788f4da7301e9244d77a7fd3fc Mon Sep 17 00:00:00 2001 From: Davis Rollman Date: Tue, 14 Apr 2026 12:23:09 -0400 Subject: [PATCH 2/3] Trim default Gradle build outputs --- .github/workflows/main.yml | 11 ++++---- CONTRIBUTING.md | 6 ++-- README.md | 6 ++-- common.gradle | 56 +++++++++++++++++++++++--------------- gradle.properties | 10 +++---- jme3-examples/build.gradle | 7 +++-- 6 files changed, 57 insertions(+), 39 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c1984ce194..3716e2e61c 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() @@ -285,8 +285,7 @@ jobs: shell: bash run: | # Normal build plus ZIP distribution and merged javadoc - ./gradlew -PuseCommitHashAsVersionName=true -PskipPrebuildLibraries=true \ - -x checkstyleMain -x checkstyleTest \ + ./gradlew -PuseCommitHashAsVersionName=true -PskipPrebuildLibraries=true -PbuildJavaDoc=true \ build createZipDistribution mergedJavadoc if [ "${{ matrix.deploy }}" = "true" ]; @@ -306,13 +305,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 @@ -491,6 +490,7 @@ jobs: -PsigningKey='${{ secrets.SIGNING_KEY }}' \ -PsigningPassword='${{ secrets.SIGNING_PASSWORD }}' \ -PuseCommitHashAsVersionName=true \ + -PbuildJavaDoc=true \ --console=plain --stacktrace fi @@ -554,6 +554,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/common.gradle b/common.gradle index 5cbd69c5fc..31c8a3827f 100644 --- a/common.gradle +++ b/common.gradle @@ -3,7 +3,15 @@ // apply plugin: 'java-library' -apply plugin: 'groovy' +group = 'org.jmonkeyengine' +version = jmeFullVersion + +def groovySourcePresent = project.file('src/main/groovy').exists() || project.file('src/test/groovy').exists() + +if (groovySourcePresent) { + apply plugin: 'groovy' +} + apply plugin: 'maven-publish' apply plugin: 'signing' apply plugin: 'eclipse' @@ -12,15 +20,13 @@ apply plugin: 'checkstyle' eclipse.jdt.file.withProperties { props -> props.setProperty "org.eclipse.jdt.core.circularClasspath", "warning" } -group = 'org.jmonkeyengine' -version = jmeFullVersion 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' @@ -42,8 +48,10 @@ dependencies { testImplementation libs.junit.jupiter testImplementation libs.mokito.core testImplementation libs.mokito.junit.jupiter - testImplementation libs.groovy.test testRuntimeOnly libs.junit.platform.launcher + if (groovySourcePresent) { + testImplementation libs.groovy.test + } } // Uncomment if you want to see the status of every test that is run and @@ -65,7 +73,7 @@ jar { } } -javadoc { +tasks.named('javadoc', Javadoc) { failOnError = false options.memberLevel = org.gradle.external.javadoc.JavadocMemberLevel.PROTECTED options.docTitle = "jMonkeyEngine ${jmeFullVersion} ${project.name} Javadoc" @@ -88,14 +96,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 = { @@ -123,18 +135,16 @@ ext.pomConfig = { } } -tasks.named('assemble') { - dependsOn sourcesJar - if (buildJavaDoc == "true") { - dependsOn javadocJar - } -} +def hasSigningKey = providers.gradleProperty('signingKey').isPresent() +def publishedModuleName = "${project.name}-${jmeFullVersion}" publishing { publications { maven(MavenPublication) { - artifact javadocJar artifact sourcesJar + if (buildJavaDoc == "true") { + artifact javadocJar + } from components.java pom { description = POM_DESCRIPTION @@ -195,10 +205,12 @@ publishing { } } -publishToMavenLocal.doLast { - println 'published ' + project.getName() + "-${jmeFullVersion} to mavenLocal" +tasks.named('publishToMavenLocal') { + doLast { + println "published ${publishedModuleName} to mavenLocal" + } } -task('install') { +tasks.register('install') { dependsOn 'publishToMavenLocal' } @@ -209,8 +221,8 @@ signing { sign publishing.publications.maven } -tasks.withType(Sign) { - onlyIf { gradle.rootProject.hasProperty('signingKey') } +tasks.withType(Sign).configureEach { + onlyIf { hasSigningKey } } def checkstyleSupported = JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_21) @@ -228,7 +240,7 @@ checkstyleTest { source ='src/test/java' } -tasks.withType(Checkstyle) { +tasks.withType(Checkstyle).configureEach { enabled = checkstyleSupported reports { xml.required.set(false) diff --git a/gradle.properties b/gradle.properties index d924be823d..8500d0f52d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,11 +12,11 @@ useCommitHashAsVersionName = false # generated version. includeBranchInVersion = false -# specify if JavaDoc should be built -buildJavaDoc = true - -# specify if SDK and Native libraries get built -buildNativeProjects = false +# specify if JavaDoc should be built +buildJavaDoc = false + +# specify if SDK and Native libraries get built +buildNativeProjects = false buildAndroidExamples = false buildForPlatforms = Linux64,Linux32,Windows64,Windows32,Mac64 diff --git a/jme3-examples/build.gradle b/jme3-examples/build.gradle index b3468883cc..4de4b88513 100644 --- a/jme3-examples/build.gradle +++ b/jme3-examples/build.gradle @@ -1,10 +1,11 @@ -ext.mainClassName = 'jme3test.TestChooser' +def examplesMainClassName = 'jme3test.TestChooser' +ext.mainClassName = examplesMainClassName def androidProject = project(':jme3-android') def androidNativeProject = project(':jme3-android-native') task run(dependsOn: 'build', type:JavaExec) { - mainClass = mainClassName + mainClass = examplesMainClassName classpath = sourceSets.main.runtimeClasspath if (System.properties['java.util.logging.config.file'] != null) { @@ -46,7 +47,7 @@ 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/' + From dfab9a7ea00aa3019d24722f8919d634eab7b2d6 Mon Sep 17 00:00:00 2001 From: Davis Rollman Date: Tue, 14 Apr 2026 12:24:45 -0400 Subject: [PATCH 3/3] Make distribution tasks configuration-cache-friendly --- build.gradle | 129 ++++++++++++++++++------------- gradle.properties | 5 ++ jme3-android-native/build.gradle | 11 +++ jme3-examples/build.gradle | 70 ++++++++++------- jme3-ios-native/build.gradle | 7 +- 5 files changed, 140 insertions(+), 82 deletions(-) diff --git a/build.gradle b/build.gradle index 364a050846..20ba1c8c9a 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} } } } @@ -145,7 +165,13 @@ def mergedJavadocSubprojects = [ ":jme3-plugins", ":jme3-terrain", ] +def mergedJavadocClasspath = providers.provider { + mergedJavadocSubprojects.collectMany { projectPath -> + project(projectPath).sourceSets.main.compileClasspath.files as List + } +} 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 +183,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(mergedJavadocClasspath) } def cleanMergedJavadoc = tasks.register('cleanMergedJavadoc', Delete) { @@ -197,37 +223,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 +256,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/gradle.properties b/gradle.properties index 8500d0f52d..5ee00a5560 100644 --- a/gradle.properties +++ b/gradle.properties @@ -15,6 +15,11 @@ includeBranchInVersion = false # 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 buildAndroidExamples = false diff --git a/jme3-android-native/build.gradle b/jme3-android-native/build.gradle index 5ec15daea1..691f9e39ef 100644 --- a/jme3-android-native/build.gradle +++ b/jme3-android-native/build.gradle @@ -33,3 +33,14 @@ ext { apply from: file('openalsoft.gradle') apply from: file('decode.gradle') apply from: file('bufferallocator.gradle') + +def androidCompileJava = project(':jme3-android').tasks.named('compileJava') +tasks.named('copyJmeHeadersOpenAL') { + dependsOn androidCompileJava +} +tasks.named('copyJmeHeadersDecode') { + dependsOn androidCompileJava +} +tasks.named('copyJmeHeadersBufferAllocator') { + dependsOn androidCompileJava +} diff --git a/jme3-examples/build.gradle b/jme3-examples/build.gradle index 4de4b88513..c58f25e040 100644 --- a/jme3-examples/build.gradle +++ b/jme3-examples/build.gradle @@ -3,8 +3,23 @@ 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) { +tasks.register('run', JavaExec) { + dependsOn sourceSets.main.runtimeClasspath mainClass = examplesMainClassName classpath = sourceSets.main.runtimeClasspath @@ -49,45 +64,48 @@ jar.doFirst{ // 'Implementation-Vendor' : vendor, '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-ios-native/build.gradle b/jme3-ios-native/build.gradle index 5f0b6304bd..3b01f52af9 100644 --- a/jme3-ios-native/build.gradle +++ b/jme3-ios-native/build.gradle @@ -4,14 +4,17 @@ def deleteXcframework = tasks.register('deleteXcframework', Delete) { delete 'template/META-INF/robovm/ios/libs/jme3-ios-native.xcframework' } +def iosDeviceDerivedDataPath = layout.buildDirectory.dir('derivedData/ios') +def iosSimulatorDerivedDataPath = layout.buildDirectory.dir('derivedData/ios-simulator') + def buildNativeLibIos = tasks.register('buildNativeLibIos', Exec) { executable "xcodebuild" - args 'archive', '-project', 'jme3-ios-native.xcodeproj', '-scheme', 'jme3-ios-native', '-configuration', 'release', '-destination', 'generic/platform=iOS', '-archivePath', 'build/archives/jme3-ios-native_iOS', 'SKIP_INSTALL=NO', 'BUILD_LIBRARY_FOR_DISTRIBUTION=YES' + args 'archive', '-project', 'jme3-ios-native.xcodeproj', '-scheme', 'jme3-ios-native', '-configuration', 'release', '-destination', 'generic/platform=iOS', '-derivedDataPath', iosDeviceDerivedDataPath.get().asFile.absolutePath, '-archivePath', 'build/archives/jme3-ios-native_iOS', 'SKIP_INSTALL=NO', 'BUILD_LIBRARY_FOR_DISTRIBUTION=YES' } def buildNativeLibSimulator = tasks.register('buildNativeLibSimulator', Exec) { executable "xcodebuild" - args 'archive', '-project', 'jme3-ios-native.xcodeproj', '-scheme', 'jme3-ios-native', '-configuration', 'release', '-destination', 'generic/platform=iOS Simulator', '-archivePath', 'build/archives/jme3-ios-native_iOS-Simulator', 'SKIP_INSTALL=NO', 'BUILD_LIBRARY_FOR_DISTRIBUTION=YES' + args 'archive', '-project', 'jme3-ios-native.xcodeproj', '-scheme', 'jme3-ios-native', '-configuration', 'release', '-destination', 'generic/platform=iOS Simulator', '-derivedDataPath', iosSimulatorDerivedDataPath.get().asFile.absolutePath, '-archivePath', 'build/archives/jme3-ios-native_iOS-Simulator', 'SKIP_INSTALL=NO', 'BUILD_LIBRARY_FOR_DISTRIBUTION=YES' } def buildNativeLib = tasks.register('buildNativeLib', Exec) {