diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 89e79a9..288d784 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -69,7 +69,7 @@ jobs: strategy: matrix: os: [ 'ubuntu-latest', 'windows-latest' ] - jdk: ['17', '19'] + jdk: ['17', '20', '27'] architecture: ['x86_64'] # Steps represent a sequence of tasks that will be executed as part of the job @@ -105,7 +105,7 @@ jobs: run: ./gradlew :snaploader-examples:TestCpuFeatures :snaploader-examples:run - name: Run TestBrokenFeatures - run: ./gradlew :snaploader-examples:ReflectiveLauncher :snaploader-examples:run --args="electrostatic4j.snaploader.examples.TestBrokenFeatures" + run: ./gradlew :snaploader-examples:ReflectiveLauncher --args="electrostatic4j.snaploader.examples.TestBrokenFeatures" - name: List extracted files run: ls ./snaploader-examples/libs/ diff --git a/.gitignore b/.gitignore index ada0e78..978e1b5 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,6 @@ apache-maven-3.9.3 apache-maven-3.9.3-bin.tar.gz -snaploader-examples/libs \ No newline at end of file +snaploader-examples/libs + +local.properties \ No newline at end of file diff --git a/android-application/build.gradle b/android-application/build.gradle index bb75e62..e1e88b9 100644 --- a/android-application/build.gradle +++ b/android-application/build.gradle @@ -4,16 +4,17 @@ plugins { android { namespace 'electrostat.lab.snaploaderapp' - compileSdk 34 + compileSdk 37 defaultConfig { applicationId "electrostat.lab.snaploaderapp" minSdk 24 - targetSdk 34 + targetSdk 35 versionCode 1 versionName "1.0" - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + // Updated from deprecated android.support.test to androidx.test + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { @@ -23,34 +24,35 @@ android { } } compileOptions { + // Gradle 9/10 require modern Java versions (Java 17 or Java 21) for the build environment, + // but you can still target Java 8 or Java 11 for Android compatibility. sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } - packagingOptions { - exclude 'META-INF/AL2.0' - exclude 'META-INF/LGPL2.1' + + // Updated: packagingOptions is deprecated and removed in AGP 9.0+. Use packaging instead. + packaging { + resources { + excludes += '/META-INF/AL2.0' + excludes += '/META-INF/LGPL2.1' + } } } dependencies { - - implementation (project(path: ':snaploader')) { + // Updated: Changed the deprecated/removed syntax of project exclusions to the modern lazy configuration layout + implementation(project(':snaploader')) { exclude group: 'com.github.oshi', module: 'oshi-core' } - implementation 'net.java.dev.jna:jna:5.16.0@aar' - -// implementation (project(path: ':snaploader-examples')) { -// exclude group: 'com.github.oshi', module: 'oshi-core' -// exclude group: 'io.github.software-hardware-codesign', module: 'jme3-alloc-desktop' -// } + implementation 'net.java.dev.jna:jna:5.19.1@aar' implementation 'io.github.software-hardware-codesign:jme3-alloc-android:1.0.0-pre-gamma-2' - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.8.0' - implementation 'androidx.constraintlayout:constraintlayout:2.1.4' + implementation 'androidx.appcompat:appcompat:1.8.0' + implementation 'com.google.android.material:material:1.14.0' + implementation 'androidx.constraintlayout:constraintlayout:2.2.2' testImplementation 'junit:junit:4.13.2' - androidTestImplementation 'androidx.test.ext:junit:1.1.5' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' -} \ No newline at end of file + androidTestImplementation 'androidx.test.ext:junit:1.3.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.7.0' +} diff --git a/build.gradle b/build.gradle index bc41aa9..73838e2 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,5 @@ plugins { - id 'com.android.application' version '7.4.1' apply false - id 'com.android.library' version '7.4.1' apply false + // Updated: Incremented plugin versions to meet the minimum required for Gradle 9 and 10. + id 'com.android.application' version '9.3.0' apply false + id 'com.android.library' version '9.3.0' apply false } \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index c30b486..ef0abaf 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.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.8.1-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/snaploader-examples/build.gradle b/snaploader-examples/build.gradle index 57044df..c0c91ac 100644 --- a/snaploader-examples/build.gradle +++ b/snaploader-examples/build.gradle @@ -1,107 +1,89 @@ plugins { - // Apply the java-library plugin for API and implementation separation. id 'application' } -/** get system specific separated directories for the source and the destination of the dependencies */ -String dependenciesDir = "${rootDir.getPath()}/snaploader-examples/build/libs/dependencies/" -String libsDir = "${rootDir.getPath()}/snaploader/build/libs/" -final String dependencyName = "snaploader-${version}.jar" - -/** replace unix '/' with windows escaped '\' */ -if (System.getProperty("os.name").contains("Windows")) { - dependenciesDir = dependenciesDir.replaceAll("/", "\\\\") - libsDir = libsDir.replaceAll("/", "\\\\") -} +// Configuration Properties for Directories +// Note: Kept path structure clean without eager runtime os-checks during configuration phase +def dependenciesDir = layout.buildDirectory.dir("libs/dependencies").get().asFile.absolutePath +def libsDir = project(':snaploader').layout.buildDirectory.dir("libs").get().asFile.absolutePath application { - mainClass = 'electrostatic4j.snaploader.examples.TestBasicFeatures' -} - -tasks.register("TestBasicFeatures") { - application.mainClass = 'electrostatic4j.snaploader.examples.TestBasicFeatures' -} - -tasks.register("TestBasicFeatures2") { - application.mainClass = 'electrostatic4j.snaploader.examples.TestBasicFeatures2' -} - -tasks.register("TestCpuFeatures", JavaExec) { - classpath sourceSets.main.runtimeClasspath - description = 'Runs the TestCpuFeatures example app.' - mainClass = 'electrostatic4j.snaploader.examples.TestCpuFeatures' -} - -tasks.register("MonitorableExample") { - application.mainClass = 'electrostatic4j.snaploader.examples.MonitorableExample' -} - -tasks.register("ReflectiveLauncher") { - application.mainClass = 'electrostatic4j.snaploader.examples.ReflectiveLauncher' + // Updated: In Gradle 9+, mainClass is a lazy Property and should be assigned cleanly + mainClass.set('electrostatic4j.snaploader.examples.TestBasicFeatures') } -tasks.register("TestMultipleLoads") { - application.mainClass = 'electrostatic4j.snaploader.examples.TestMultipleLoads' -} - -tasks.register("TestZipExtractor") { - application.mainClass = 'electrostatic4j.snaploader.examples.TestZipExtractor' -} - -tasks.register("TestMultiThreading") { - application.mainClass = 'electrostatic4j.snaploader.examples.TestMultiThreading' -} - -tasks.register("TestRetryExhaustionException") { - application.mainClass = 'electrostatic4j.snaploader.examples.TestRetryExhaustionException' +// Helper method to eliminate duplicate boilerplate for registering executable example tasks +def registerExampleTask(String taskName, String mainClassName) { + tasks.register(taskName, JavaExec) { + group = 'application' + description = "Runs the ${taskName} example app." + classpath = sourceSets.main.runtimeClasspath + mainClass.set(mainClassName) + } } -task copyLibs(type: Copy) { - from (libsDir) { +// Updated: Converted all plain tasks that previously mutated a global variable into proper standalone JavaExec tasks. +registerExampleTask("TestBasicFeatures", 'electrostatic4j.snaploader.examples.TestBasicFeatures') +registerExampleTask("TestBasicFeatures2", 'electrostatic4j.snaploader.examples.TestBasicFeatures2') +registerExampleTask("TestCpuFeatures", 'electrostatic4j.snaploader.examples.TestCpuFeatures') +registerExampleTask("MonitorableExample", 'electrostatic4j.snaploader.examples.MonitorableExample') +registerExampleTask("ReflectiveLauncher", 'electrostatic4j.snaploader.examples.ReflectiveLauncher') +registerExampleTask("TestMultipleLoads", 'electrostatic4j.snaploader.examples.TestMultipleLoads') +registerExampleTask("TestZipExtractor", 'electrostatic4j.snaploader.examples.TestZipExtractor') +registerExampleTask("TestMultiThreading", 'electrostatic4j.snaploader.examples.TestMultiThreading') +registerExampleTask("TestRetryExhaustionException", 'electrostatic4j.snaploader.examples.TestRetryExhaustionException') + +// Updated: Changed legacy "task name(type: Copy)" layout to modern "tasks.register" syntax +tasks.register("copyLibs", Copy) { + from(libsDir) { include '**/*.jar' } into(dependenciesDir) includeEmptyDirs = false - setDuplicatesStrategy(DuplicatesStrategy.EXCLUDE) + duplicatesStrategy = DuplicatesStrategy.EXCLUDE } -/** Assembles a jar file with a class-path loading the dependencies and a main-class */ -task createJar(type : Jar, dependsOn : copyLibs){ - //get the copied jars - String dependenciesString = "" - final File dependencies = new File(dependenciesDir) - if(dependencies.exists()) { - if (dependencies.listFiles().length > 0) { - final File[] files = dependencies.listFiles() - for (int i = 0; i < files.length; i++) { - final String fileName = files[i].getName() - if (fileName.contains(".jar")) { - /** All zip paths are unix paths; so no need to the file system specific separator */ - dependenciesString += "dependencies/" + fileName + " " +// Updated: Changed legacy task declaration and moved imperative file-system reading +// inside "doFirst" block to make it fully compatible with Gradle 9+ Configuration Caching. +tasks.register("createJar", Jar) { + dependsOn(tasks.named('copyLibs')) + + // Mixin the base jar behaviors cleanly using modern named task mapping + from(sourceSets.main.output) + + doFirst { + String dependenciesString = "" + File dependenciesFolder = new File(dependenciesDir) + if (dependenciesFolder.exists()) { + File[] files = dependenciesFolder.listFiles() + if (files != null && files.length > 0) { + for (File file : files) { + String fileName = file.getName() + if (fileName.endsWith(".jar")) { + dependenciesString += "dependencies/" + fileName + " " + } } } } - } - manifest { - attributes 'Project': 'snaploader-examples', - 'Automatic-Module-Name': "${project.name.replace("-", ".")}", - 'Compiled-by': JavaVersion.current(), - 'Class-Path': dependenciesString, - 'Main-Class': application.mainClass + manifest { + attributes 'Project': 'snaploader-examples', + 'Automatic-Module-Name': project.name.replace("-", "."), + 'Compiled-by': JavaVersion.current(), + 'Class-Path': dependenciesString.trim(), + 'Main-Class': application.mainClass.get() + } } - with jar } - dependencies { - implementation project(path: ':snaploader') - implementation 'org.apache.logging.log4j:log4j-slf4j2-impl:2.24.3' - - implementation 'com.github.stephengold:jolt-jni-Linux64:0.9.7' - runtimeOnly 'com.github.stephengold:jolt-jni-Linux64:0.9.7:DebugSp' - runtimeOnly 'com.github.stephengold:jolt-jni-Linux64_fma:0.9.7:DebugSp' - runtimeOnly 'com.github.stephengold:jolt-jni-Windows64:0.9.7:DebugSp' - runtimeOnly 'com.github.stephengold:jolt-jni-Windows64_avx2:0.9.7:DebugSp' + implementation project(':snaploader') + implementation 'org.apache.logging.log4j:log4j-slf4j2-impl:2.26.1' + + implementation 'com.github.stephengold:jolt-jni-Linux64:6.1.1' + runtimeOnly 'com.github.stephengold:jolt-jni-Linux64:6.1.1:DebugSp' + runtimeOnly 'com.github.stephengold:jolt-jni-Linux64_fma:6.1.1:DebugSp' + runtimeOnly 'com.github.stephengold:jolt-jni-Windows64:6.1.1:DebugSp' + runtimeOnly 'com.github.stephengold:jolt-jni-Windows64_avx2:6.1.1:DebugSp' runtimeOnly 'io.github.software-hardware-codesign:jme3-alloc-desktop:1.0.0-pre-gamma-2' -} \ No newline at end of file +} diff --git a/snaploader/build.gradle b/snaploader/build.gradle index 5aaaa3f..7b5834e 100644 --- a/snaploader/build.gradle +++ b/snaploader/build.gradle @@ -3,9 +3,11 @@ plugins { id 'java-library' } +// Updated: Use the type-safe task registration syntax and replace lazy property `.from` references +// with exact task target mapping to ensure Configuration Cache compliance. tasks.register("generateJavadocJar", Jar) { archiveClassifier.set("javadoc") - from javadoc + from tasks.named('javadoc') } tasks.register("generateSourcesJar", Jar) { @@ -13,19 +15,29 @@ tasks.register("generateSourcesJar", Jar) { from sourceSets.main.allSource } -tasks.withType(JavaCompile) { - options.release = 8 +tasks.withType(JavaCompile).configureEach { + // Updated: In Gradle 9+, compiler options (like release) use lazy Property types. + // They must be assigned via .set() rather than raw assignment. + options.release.set(8) } -jar { // assemble jar options [java -jar] +jar { manifest { + // Updated: Replaced project.name string mutation inside the manifest block + // to directly read the property without relying on dynamic Groovy resolution. attributes 'Project': "jSnaploader", - 'Version': "${version}", - 'Automatic-Module-Name': "${project.name.replace("-", ".")}", - 'Compiled-by': JavaVersion.current() + 'Version': "${version}", + 'Automatic-Module-Name': project.name.replace("-", "."), + 'Compiled-by': JavaVersion.current() } } dependencies { - api('com.github.oshi:oshi-core:6.7.0') + // Standardized api configuration notation for Gradle 9/10 + api 'com.github.oshi:oshi-core:7.7.0' } + +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 +} \ No newline at end of file