diff --git a/.github/workflows/build-and-verify-alignment.yml b/.github/workflows/build-and-verify-alignment.yml new file mode 100644 index 0000000..827f0d6 --- /dev/null +++ b/.github/workflows/build-and-verify-alignment.yml @@ -0,0 +1,171 @@ +name: Build and Verify 16KB Page Size Alignment + +on: + push: + branches: [ master, main, develop ] + pull_request: + branches: [ master, main, develop ] + +jobs: + build-and-verify: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + + - name: Setup Android SDK + uses: android-actions/setup-android@v3 + + - name: Cache Gradle packages + uses: actions/cache@v4 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle- + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Build with Gradle + run: ./gradlew build + + - name: Verify 16KB Page Size Alignment + run: | + echo "🔍 Checking 16KB page size alignment of 64-bit native libraries..." + + # Function to check alignment of a shared library + check_alignment() { + local lib_path="$1" + local lib_name=$(basename "$lib_path") + + echo "Checking $lib_name..." + + # Use llvm-readelf from NDK to check alignment + local ndk_path="$ANDROID_NDK_ROOT" + local readelf="$ndk_path/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-readelf" + + if [ ! -f "$readelf" ]; then + echo "❌ Error: llvm-readelf not found at $readelf" + return 1 + fi + + # Check LOAD segments alignment + local alignments=$($readelf -l "$lib_path" | grep "LOAD" | awk '{print $NF}') + + local all_aligned=true + for alignment in $alignments; do + # Convert hex to decimal + local decimal_alignment=$((alignment)) + local kb_alignment=$((decimal_alignment / 1024)) + + echo " Segment alignment: $alignment ($decimal_alignment bytes = ${kb_alignment}KB)" + + if [ $decimal_alignment -ne 16384 ]; then + echo " ❌ Not 16KB aligned (expected 0x4000 = 16384 bytes)" + all_aligned=false + else + echo " ✅ 16KB aligned" + fi + done + + if [ "$all_aligned" = true ]; then + echo "✅ $lib_name is properly 16KB aligned" + return 0 + else + echo "❌ $lib_name has incorrect alignment" + return 1 + fi + } + + # Find all .so files in build outputs (64-bit architectures only) + echo "Finding 64-bit native libraries in build outputs..." + so_files=$(find . -path "*/build/intermediates/cxx/*/obj/*/*.so" -type f | grep -E "(Release|RelWithDebInfo)" | grep -E "(arm64-v8a|x86_64)" | head -20) + + if [ -z "$so_files" ]; then + echo "❌ No native libraries found in build outputs" + exit 1 + fi + + echo "Found native libraries:" + echo "$so_files" + echo + + # Check alignment for each library + all_libs_aligned=true + for so_file in $so_files; do + if ! check_alignment "$so_file"; then + all_libs_aligned=false + fi + echo + done + + # Summary + echo "📊 Alignment Verification Summary:" + if [ "$all_libs_aligned" = true ]; then + echo "🎉 All native libraries are properly 16KB aligned!" + echo "✅ This build is compatible with 16KB page size devices" + else + echo "❌ Some libraries are not properly aligned" + echo "💡 Ensure you're using Android Gradle Plugin 8.5.1+ and target SDK 35+" + exit 1 + fi + + - name: Verify AAR Contents + run: | + echo "🔍 Verifying AAR files contain native libraries..." + + # Find AAR files + aar_files=$(find . -name "*.aar" -path "*/build/outputs/aar/*" -type f) + + if [ -z "$aar_files" ]; then + echo "❌ No AAR files found" + exit 1 + fi + + echo "Found AAR files:" + for aar in $aar_files; do + echo "đŸ“Ļ $(basename $aar)" + + # Check if AAR contains native libraries + native_libs=$(unzip -l "$aar" | grep -E "jni/.*\.so$" | wc -l) + + if [ $native_libs -gt 0 ]; then + echo " ✅ Contains $native_libs native libraries" + echo " 📋 Native library details:" + unzip -l "$aar" | grep -E "jni/.*\.so$" | awk '{print " " $4}' + else + echo " â„šī¸ No native libraries (library may be pure Java/Kotlin)" + fi + echo + done + + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + if: always() + with: + name: build-outputs + path: | + **/build/outputs/aar/*.aar + **/build/intermediates/cxx/*/obj/*/*.so + retention-days: 7 + + - name: Upload lint reports + uses: actions/upload-artifact@v4 + if: always() + with: + name: lint-reports + path: | + **/build/reports/lint-results-*.html + retention-days: 7 \ No newline at end of file diff --git a/.gitignore b/.gitignore index 08a38dc..07d4618 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ /captures /local.properties .externalNativeBuild -.cxx \ No newline at end of file +.cxx +.java-version \ No newline at end of file diff --git a/README.md b/README.md index b94d71b..4c82968 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,20 @@ -DashJ BLS for Android +# DashJ BLS for Android ```bash git submodule update --init --recursive ./gradlew build ``` -Publish to Maven Local +### Publish to Maven Local ``` ./gradlew publishToMavenLocal ``` -Publish to Maven Central -``` + +### Publish to Maven Central + +To deploy to the maven repository: +```bash +./gradlew clean ./gradlew publish +./gradlew jreleaserDeploy ``` \ No newline at end of file diff --git a/build.gradle b/build.gradle index 27c35c0..64e7bfe 100644 --- a/build.gradle +++ b/build.gradle @@ -1,20 +1,17 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.5.20' + ext.kotlin_version = '2.1.20' repositories { mavenLocal() mavenCentral() google() + gradlePluginPortal() // Required for JReleaser plugin } dependencies { - classpath 'com.android.tools.build:gradle:7.2.2' + classpath 'com.android.tools.build:gradle:8.5.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - - //classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.4.1' - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files } } diff --git a/dashj-bls/build.gradle b/dashj-bls/build.gradle index 9671911..8357f6d 100644 --- a/dashj-bls/build.gradle +++ b/dashj-bls/build.gradle @@ -4,15 +4,18 @@ plugins { id 'signing' id 'kotlin-android' id 'kotlin-kapt' + id 'org.jreleaser' version '1.17.0' } +version "1.0.1-SNAPSHOT" android { - compileSdkVersion 31 + namespace "org.dashj.bls" + compileSdkVersion 34 defaultConfig { minSdkVersion 23 - targetSdkVersion 31 + targetSdkVersion 35 versionCode 1 - versionName "1.0.0" + versionName "$version" defaultConfig { ndk { @@ -36,33 +39,32 @@ android { main.java.srcDirs += 'src/main/java' } - kotlinOptions { jvmTarget = '1.8' } + kotlinOptions { jvmTarget = '17' } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 } externalNativeBuild { cmake { path 'src/main/cpp/CMakeLists.txt' - version '3.18.1' + version '3.22.1' } } - ndkVersion '23.2.8568313' + ndkVersion '29.0.14206865' publishing { singleVariant("release") { // if you don't want sources/javadoc, remove these lines - withSourcesJar() + //withSourcesJar() //withJavadocJar() } } } -version '1.0.0' - dependencies { - api 'org.dashj:dashj-bls:1.0.0' + api 'org.dashj:dashj-bls:1.0.1' + testImplementation 'junit:junit:4.13.2' } repositories { @@ -71,18 +73,21 @@ repositories { } task javadoc(type: Javadoc) { - source = android.sourceSets.main.java.srcDirs + source = fileTree(dir: 'src/main/java', include: '**/*.java') classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) + exclude '**/BuildConfig.java' + exclude '**/R.java' + failOnError false } -task javadocJar(type: Jar, dependsOn: javadoc) { - classifier = 'javadoc' - from javadoc.destinationDir +task javadocJar(type: Jar) { + archiveClassifier = 'javadoc' + // Create empty javadoc jar for now } task sourcesJar(type: Jar) { from android.sourceSets.main.java.srcDirs - classifier = 'sources' + archiveClassifier = 'sources' } artifacts { @@ -99,23 +104,28 @@ task comps { } afterEvaluate { + def projectVersion = version + publishing { publications { release(MavenPublication) { groupId group artifactId 'dashj-bls-android' - version "$version" + version projectVersion from components.release pom { name = 'DashJ-BLS-Android' description = 'Dash BLS Android Library' - url = 'httsp://dashj.org' + url = 'https://github.com/dashpay/dashj-android' + + // Override packaging to jar for Maven Central compatibility + packaging = 'jar' licenses { license { - name = 'MIT' - url = 'https://opensource.org/licenses/MIT' + name = 'The Apache License, Version 2.0' + url = 'http://www.apache.org/licenses/LICENSE-2.0.txt' } } developers { @@ -135,20 +145,52 @@ afterEvaluate { } repositories { maven { - // change URLs to point to your repos, e.g. http://my.org/repo - def releasesRepoUrl = "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/" - def snapshotsRepoUrl = "https://s01.oss.sonatype.org/content/repositories/snapshots/" - url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl - credentials { - username = project.hasProperty('ossrhUsername') ? project.findProperty('ossrhUsername') : '' - password = project.hasProperty('ossrhPassword') ? project.findProperty('ossrhPassword') : '' + url = layout.buildDirectory.dir('staging-deploy') + } + } + } + jreleaser { + project { + name = 'dashj-bls-android' + description = 'Dash BLS Android Library' + website = 'https://github.com/dashpay/dashj-android' + authors = ['HashEngineering'] + license = 'The Apache License, Version 2.0' + gitRootSearch = true + version = projectVersion + } + + signing { + active = 'ALWAYS' + armored = true + } + + deploy { + maven { + mavenCentral { + sonatype { + active = 'ALWAYS' + url = 'https://central.sonatype.com/api/v1/publisher' + stagingRepository("$buildDir/staging-deploy") + } + } + nexus2 { + app { + active = 'SNAPSHOT' + url = 'https://central.sonatype.com/repository/maven-snapshots/' + snapshotUrl = 'https://central.sonatype.com/repository/maven-snapshots/' + applyMavenCentralRules = false // must be false for aar + snapshotSupported = true + closeRepository = true + releaseRepository = true + stagingRepository("$buildDir/staging-deploy") + } } } } } signing { required { gradle.taskGraph.hasTask("publish") } - println("Components: " + publishing.publications) sign publishing.publications.release } } \ No newline at end of file diff --git a/dashj-scrypt/build.gradle b/dashj-scrypt/build.gradle index ebbf17e..e249082 100644 --- a/dashj-scrypt/build.gradle +++ b/dashj-scrypt/build.gradle @@ -2,19 +2,20 @@ plugins { id 'com.android.library' id 'maven-publish' id 'signing' + id 'org.jreleaser' version '1.17.0' } -version "0.17.5" +version "1.0.0-SNAPSHOT" android { - compileSdkVersion 29 - buildToolsVersion "29.0.3" + namespace "org.dashj.scrypt" + compileSdkVersion 34 defaultConfig { - minSdkVersion 19 - targetSdkVersion 29 - versionCode 1 - versionName "0.17.5" + minSdkVersion 21 + targetSdkVersion 35 + versionCode 2 + versionName "$version" } buildTypes { @@ -24,8 +25,8 @@ android { } } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 } externalNativeBuild { @@ -33,6 +34,13 @@ android { path 'src/main/cpp/CMakeLists.txt' } } + ndkVersion '29.0.14206865' + + publishing { + singleVariant("release") { + withSourcesJar() + } + } } dependencies { @@ -45,18 +53,91 @@ task javadoc(type: Javadoc) { } task javadocJar(type: Jar, dependsOn: javadoc) { - classifier = 'javadoc' + archiveClassifier = 'javadoc' from javadoc.destinationDir } task sourcesJar(type: Jar) { from android.sourceSets.main.java.srcDirs - classifier = 'sources' + archiveClassifier = 'sources' } +//artifacts { +// archives javadocJar +// archives sourcesJar +//} + + + +//afterEvaluate { +// publishing { +// publications { +// release(MavenPublication) { +// groupId group +// artifactId 'dashj-scrypt-android' +// version "$version" +// from components.java +// +// pom { +// name = 'DashJ Scrypt' +// description = 'DashJ Scrypt Libary for Android' +// url = 'https://github.com/HashEngineering/dashj-android' +// +// licenses { +// license { +// name = 'MIT' +// url = 'https://opensource.org/licenses/MIT' +// } +// } +// developers { +// developer { +// id = 'hashengineering' +// name = 'HashEngineering' +// email = 'hashengineeringsolutions@gmail.com' +// } +// } +// scm { +// connection = 'scm:git:git://github.com/dashpay/dashj-android.git' +// developerConnection = 'scm:git:ssh://github.com/dashpay/dashj-android.git' +// url = 'http://github.com/dashpay/dashj-android.git' +// } +// } +// } +// } +// repositories { +// maven { +// // change URLs to point to your repos, e.g. http://my.org/repo +// def releasesRepoUrl = "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/" +// def snapshotsRepoUrl = "https://s01.oss.sonatype.org/content/repositories/snapshots/" +// url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl +// credentials { +// username = project.hasProperty('ossrhUsername') ? project.findProperty('ossrhUsername') : '' +// password = project.hasProperty('ossrhPassword') ? project.findProperty('ossrhPassword') : '' +// } +// } +// } +// } +// signing { +// required { gradle.taskGraph.hasTask("publish") } +// println("Components: " + publishing.publications) +// sign publishing.publications.release +// } +//} + +//task javadocJar(type: Jar, dependsOn: javadoc) { +// archiveClassifier = 'javadoc' +// from javadoc.destinationDir +//} +// +//task sourcesJar(type: Jar, dependsOn: classes) { +// archiveClassifier = 'sources' +// from sourceSets.main.allSource +// duplicatesStrategy = DuplicatesStrategy.EXCLUDE // or DuplicatesStrategy.WARN +//} + artifacts { - archives javadocJar archives sourcesJar + archives javadocJar } assemble.dependsOn(publishToMavenLocal) @@ -68,23 +149,28 @@ task comps { } afterEvaluate { + def projectVersion = version + publishing { publications { release(MavenPublication) { groupId group - artifactId 'dashj-scrypt-android' - version "$version" + artifactId = 'dashj-scrypt-android' + version projectVersion from components.release pom { name = 'DashJ Scrypt' description = 'DashJ Scrypt Libary for Android' - url = 'https://github.com/HashEngineering/dashj-bls-android' + url = 'https://github.com/dashpay/dashj-android' + + // Override packaging to jar for Maven Central compatibility + packaging = 'jar' licenses { license { - name = 'MIT' - url = 'https://opensource.org/licenses/MIT' + name = 'The Apache License, Version 2.0' + url = 'http://www.apache.org/licenses/LICENSE-2.0.txt' } } developers { @@ -104,20 +190,53 @@ afterEvaluate { } repositories { maven { - // change URLs to point to your repos, e.g. http://my.org/repo - def releasesRepoUrl = "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/" - def snapshotsRepoUrl = "https://s01.oss.sonatype.org/content/repositories/snapshots/" - url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl - credentials { - username = project.hasProperty('ossrhUsername') ? project.findProperty('ossrhUsername') : '' - password = project.hasProperty('ossrhPassword') ? project.findProperty('ossrhPassword') : '' + url = layout.buildDirectory.dir('staging-deploy') + } + } + } + jreleaser { + project { + name = 'dashj-scrypt-android' + description = 'DashJ Scrypt Libary for Android' + website = 'https://github.com/dashpay/dashj-android' + authors = ['HashEngineering'] + license = 'The Apache License, Version 2.0' + gitRootSearch = true + version = projectVersion + } + + signing { + active = 'ALWAYS' + armored = true + } + + deploy { + maven { + mavenCentral { + sonatype { + active = 'ALWAYS' + url = 'https://central.sonatype.com/api/v1/publisher' + stagingRepository("$buildDir/staging-deploy") + } + } + nexus2 { + app { + active = 'SNAPSHOT' + url = 'https://central.sonatype.com/repository/maven-snapshots/' + snapshotUrl = 'https://central.sonatype.com/repository/maven-snapshots/' + applyMavenCentralRules = false // must be false for aar + snapshotSupported = true + closeRepository = true + releaseRepository = true + stagingRepository("$buildDir/staging-deploy") + } } } } } signing { required { gradle.taskGraph.hasTask("publish") } - println("Components: " + publishing.publications) sign publishing.publications.release } -} \ No newline at end of file +} + diff --git a/dashj-x11/build.gradle b/dashj-x11/build.gradle index 3a44f53..01e5c41 100644 --- a/dashj-x11/build.gradle +++ b/dashj-x11/build.gradle @@ -2,19 +2,20 @@ plugins { id 'com.android.library' id 'maven-publish' id 'signing' + id 'org.jreleaser' version '1.17.0' } -version "0.17.5" +version "1.0.0-SNAPSHOT" android { - compileSdkVersion 29 - buildToolsVersion "29.0.3" + namespace "org.dashj.x11" + compileSdkVersion 34 defaultConfig { - minSdkVersion 19 - targetSdkVersion 29 + minSdkVersion 21 + targetSdkVersion 35 versionCode 1 - versionName "0.17.5" + versionName "$version" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro" @@ -27,8 +28,8 @@ android { } } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 } externalNativeBuild { @@ -36,10 +37,16 @@ android { path 'src/main/cpp/CMakeLists.txt' } } + ndkVersion '29.0.14206865' + + publishing { + singleVariant("release") { + } + } } dependencies { - + testImplementation 'junit:junit:4.13.2' } task javadoc(type: Javadoc) { @@ -48,13 +55,13 @@ task javadoc(type: Javadoc) { } task javadocJar(type: Jar, dependsOn: javadoc) { - classifier = 'javadoc' + archiveClassifier = 'javadoc' from javadoc.destinationDir } task sourcesJar(type: Jar) { from android.sourceSets.main.java.srcDirs - classifier = 'sources' + archiveClassifier = 'sources' } artifacts { @@ -71,23 +78,28 @@ task comps { } afterEvaluate { + def projectVersion = version + publishing { publications { release(MavenPublication) { groupId group - artifactId 'dashj-bls-android' - version "$version" + artifactId = 'dashj-x11-android' + version projectVersion from components.release pom { name = 'DashJ X11' - description = 'Dash BLS Android Library' - url = 'https://github.com/dashpay/dashj-bls-android' + description = 'DashJ X11 Library for Android' + url = 'https://github.com/dashpay/dashj-android' + + // Override packaging to jar for Maven Central compatibility + packaging = 'jar' licenses { license { - name = 'MIT' - url = 'https://opensource.org/licenses/MIT' + name = 'The Apache License, Version 2.0' + url = 'http://www.apache.org/licenses/LICENSE-2.0.txt' } } developers { @@ -107,20 +119,52 @@ afterEvaluate { } repositories { maven { - // change URLs to point to your repos, e.g. http://my.org/repo - def releasesRepoUrl = "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/" - def snapshotsRepoUrl = "https://s01.oss.sonatype.org/content/repositories/snapshots/" - url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl - credentials { - username = project.hasProperty('ossrhUsername') ? project.findProperty('ossrhUsername') : '' - password = project.hasProperty('ossrhPassword') ? project.findProperty('ossrhPassword') : '' + url = layout.buildDirectory.dir('staging-deploy') + } + } + } + jreleaser { + project { + name = 'dashj-x11-android' + description = 'DashJ X11 Library for Android' + website = 'https://github.com/dashpay/dashj-android' + authors = ['HashEngineering'] + license = 'The Apache License, Version 2.0' + gitRootSearch = true + version = projectVersion + } + + signing { + active = 'ALWAYS' + armored = true + } + + deploy { + maven { + mavenCentral { + sonatype { + active = 'ALWAYS' + url = 'https://central.sonatype.com/api/v1/publisher' + stagingRepository("$buildDir/staging-deploy") + } + } + nexus2 { + app { + active = 'SNAPSHOT' + url = 'https://central.sonatype.com/repository/maven-snapshots/' + snapshotUrl = 'https://central.sonatype.com/repository/maven-snapshots/' + applyMavenCentralRules = false // must be false for aar + snapshotSupported = true + closeRepository = true + releaseRepository = true + stagingRepository("$buildDir/staging-deploy") + } } } } } signing { required { gradle.taskGraph.hasTask("publish") } - println("Components: " + publishing.publications) sign publishing.publications.release } } @@ -151,12 +195,12 @@ uploadArchives { artifactId 'dashj-x11-android' version '0.17.5' description 'DashJ X11 Libary for Android' - url 'https://github.com/HashEngineering/dashj-bls-android' + url 'https://github.com/HashEngineering/dashj-android' scm { - connection 'scm:svn:https://github.com/HashEngineering/dashj-bls-android' - developerConnection 'scm:svn:https://github.com/HashEngineering/dashj-bls-android' - url 'https://github.com/HashEngineering/dashj-bls-android' + connection 'scm:svn:https://github.com/HashEngineering/dashj-android' + developerConnection 'scm:svn:https://github.com/HashEngineering/dashj-android' + url 'https://github.com/HashEngineering/dashj-android' } licenses { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 3133849..b02bc98 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip