diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..dfdb5eb --- /dev/null +++ b/build.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +Green='\e[32m' +NC='\033[0m' # No Color + +cd android-libkiwixbuild/ + +printf "${Green}Check Current Java version${NC}\n" +./gradlew checkCurrentJavaVersion +printf "\n${Green}Done! ${NC}\n" + +printf "${Green}Downloading libzim ${NC}\n" +./gradlew downloadLibzimSoAndHeaderFiles unzipLibzim +printf "\n${Green}Done! ${NC}\n" + +hash -r + +printf "${Green}Coping libzim header and so files ${NC}\n" +./gradlew checkCurrentLibzimDate copyLibzimHeaderFiles copyLibzimAndroidArm copyLibzimAndroidArm64 copyLibzimAndroidx86 copyLibzimAndroidx86_64 copyLibzimLinux_x86_64 renameLibzimSoFile +printf "\n${Green}Down! ${NC}\n" + +printf "${Green}Downloading libkiwix ${NC}\n" +./gradlew downloadLibkiwixSoAndHeaderFiles unzipLibkiwix +printf "\n${Green}Done! ${NC}\n" + +hash -r + +printf "${Green}Coping libkiwix header and so files ${NC}\n" +./gradlew checkCurrentLibkiwixDate copyLibkiwixHeaderFiles copyLibkiwixAndroidArm copyLibkiwixAndroidArm64 copyLibkiwixAndroidx86 copyLibkiwixAndroidx86_64 copyLibkiwixLinux_x86_64 renameLibkiwixSoFile +printf "\n${Green}Done! ${NC}\n" + +printf "${Green}Generating header files from java wrapper files ${NC}\n" +./gradlew generateHeaderFilesFromJavaWrapper +printf "\n${Green}Done! ${NC}\n" + +hash -r \ No newline at end of file diff --git a/lib/src/main/build.gradle b/lib/src/main/build.gradle new file mode 100644 index 0000000..2ba657b --- /dev/null +++ b/lib/src/main/build.gradle @@ -0,0 +1,289 @@ +import java.util.stream.Collectors + +plugins { + id 'com.android.library' + id 'org.jetbrains.kotlin.android' + id "de.undercouch.download" +} + +Properties properties = new Properties() +if (rootProject.file("local.properties").exists()) { + properties.load(rootProject.file("local.properties").newDataInputStream()) +} + +ext["keyId"] = properties.getProperty("signing.keyId", System.getenv('SIGNING_KEY_ID')) +ext["password"] = properties.getProperty("signing.password", System.getenv('SIGNING_PASSWORD')) +ext["key"] = properties.getProperty("signing.key", System.getenv('SIGNING_KEY')) +ext["ossrhUsername"] = properties.getProperty("ossrhUsername", System.getenv('OSSRH_USERNAME')) +ext["ossrhPassword"] = properties.getProperty("ossrhPassword", System.getenv('OSSRH_PASSWORD')) +ext["sonatypeStagingProfileId"] = properties.getProperty("sonatypeStagingProfileId", System.getenv('SONATYPE_STAGING_PROFILE_ID')) + +ext { + set("GROUP_ID", "org.kiwix.kiwixlib") + set("ARTIFACT_ID", "kiwixlib") + set("VERSION", "11.0.0") +} + +apply from: 'publish.gradle' +android { + compileSdk 32 + + defaultConfig { + + minSdk 21 + targetSdk 32 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + externalNativeBuild { + cmake { + cppFlags '' + arguments "-DANDROID_STL=c++_shared" + } + } + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = '1.8' + } + externalNativeBuild { + cmake { + path file('src/main/cpp/CMakeLists.txt') + version '3.18.1' + } + } + buildFeatures { + viewBinding true + } + ndkVersion '21.4.7075529' + +} + +dependencies { + implementation 'com.getkeepsafe.relinker:relinker:1.4.5' + implementation 'androidx.core:core-ktx:1.7.0' +} + +ext.libkiwix_base_url = 'https://download.kiwix.org/nightly' +ext.libzim_base_url = 'https://download.openzim.org/nightly' +// change this date to get latest libzim .so and header files +ext.nightly_date_for_libkiwix = project.properties["nightly_date_for_libkiwix"] ?: "" +ext.nightly_date_for_libzim = project.properties["nightly_date_for_libzim"] ?: "" + +ext.libkiwix_version = project.properties["libkiwix_version"] ?: "" +ext.libzim_version = project.properties["libzim_version"] ?: "" + +task downloadLibzimSoAndHeaderFiles(type: Download) { + src([ + libzim_base_url + '/libzim_android-arm.tar.gz', + libzim_base_url + '/libzim_android-arm64.tar.gz', + libzim_base_url + '/libzim_android-x86.tar.gz', + libzim_base_url + '/libzim_android-x86_64.tar.gz', + libzim_base_url + '/libzim_linux-x86_64.tar.gz' + ]) + dest buildDir + overwrite true +} + +task checkCurrentLibzimDate() { + project.ext.set("nightly_date_for_libzim", getDateFromPath(buildDir.path, "libzim_android-arm64-")) +} + +task unzipLibzim(type: Copy) { + // unzip android arm + from tarTree(buildDir.path + "/libzim_android-arm.tar.gz") + into buildDir + // unzip android arm64 + from tarTree(buildDir.path + "/libzim_android-arm64.tar.gz") + into buildDir + // unzip android x86 + from tarTree(buildDir.path + "/libzim_android-x86.tar.gz") + into buildDir + // unzip android x86_64 + from tarTree(buildDir.path + "/libzim_android-x86_64.tar.gz") + into buildDir + // unzip linux x86_64 + from tarTree(buildDir.path + "/libzim_linux-x86_64.tar.gz") + into buildDir +} + +task copyLibzimHeaderFiles(type: Copy) { + // copying header file + from buildDir.path + "/libzim_android-arm-" + nightly_date_for_libzim + '/include/' + into projectDir.path + "/src/main/cpp/include/libzim/" +} + +task copyLibzimAndroidArm(type: Copy) { + // copying android_arm so file + from buildDir.path + "/libzim_android-arm-" + nightly_date_for_libzim + '/lib/arm-linux-androideabi/' + into projectDir.path + "/src/main/jniLibs/armeabi-v7a/libzim/" +} + +task copyLibzimAndroidArm64(type: Copy) { + // copying android_arm64 so file + from buildDir.path + "/libzim_android-arm64-" + nightly_date_for_libzim + '/lib/aarch64-linux-android/' + into projectDir.path + "/src/main/jniLibs/arm64-v8a/libzim/" +} + +task copyLibzimAndroidx86(type: Copy) { + // copying android_x86 so file + from buildDir.path + "/libzim_android-x86-" + nightly_date_for_libzim + '/lib/i686-linux-android/' + into projectDir.path + "/src/main/jniLibs/x86/libzim/" +} + +task copyLibzimAndroidx86_64(type: Copy) { + // copying android_x86_64 so file + from buildDir.path + "/libzim_android-x86_64-" + nightly_date_for_libzim + '/lib/x86_64-linux-android/' + into projectDir.path + "/src/main/jniLibs/x86_64/libzim/" +} + +task copyLibzimLinux_x86_64(type: Copy) { + // copying linux_x86_64 so file + project.ext.set("libzim_version", getFileFromFolder(buildDir.path + "/libzim_linux-x86_64-" + nightly_date_for_libzim + "/lib/x86_64-linux-gnu/")) + from buildDir.path + "/libzim_linux-x86_64-" + nightly_date_for_libzim + "/lib/x86_64-linux-gnu/" + libzim_version + into buildDir.path +} + +task renameLibzimSoFile(type: Copy) { + if (libzim_version != null) { + from(buildDir.path) + include libzim_version + destinationDir file(buildDir.path) + rename libzim_version, "libzim.so" + } +} + +task downloadLibkiwixSoAndHeaderFiles(type: Download) { + src([ + libkiwix_base_url + '/libkiwix_android-arm.tar.gz', + libkiwix_base_url + '/libkiwix_android-arm64.tar.gz', + libkiwix_base_url + '/libkiwix_android-x86.tar.gz', + libkiwix_base_url + '/libkiwix_android-x86_64.tar.gz', + libkiwix_base_url + '/libkiwix_linux-x86_64.tar.gz' + ]) + dest buildDir + overwrite true +} + +task checkCurrentLibkiwixDate() { + project.ext.set("nightly_date_for_libkiwix", getDateFromPath(buildDir.path, "libkiwix_android-arm64-")) +} + +static String getDateFromPath(String path, String matchesString) { + File folder = new File(path) + if (folder.exists()) { + return folder.listFiles() + .stream() + .filter(f -> f.name.startsWith(matchesString)) + .map(s -> s.name.replace(matchesString, "")) + .collect(Collectors.toList())[0] + } +} + +task unzipLibkiwix(type: Copy) { + // unzip android arm + from tarTree(buildDir.path + "/libkiwix_android-arm.tar.gz") + into buildDir + // unzip android arm64 + from tarTree(buildDir.path + "/libkiwix_android-arm64.tar.gz") + into buildDir + // unzip android x86 + from tarTree(buildDir.path + "/libkiwix_android-x86.tar.gz") + into buildDir + // unzip android x86_64 + from tarTree(buildDir.path + "/libkiwix_android-x86_64.tar.gz") + into buildDir + // unzip linux x86_64 + from tarTree(buildDir.path + "/libkiwix_linux-x86_64.tar.gz") + into buildDir +} + +task copyLibkiwixHeaderFiles(type: Copy) { + // copying header file + from buildDir.path + "/libkiwix_android-arm-" + nightly_date_for_libkiwix + '/include/kiwix/' + into projectDir.path + "/src/main/cpp/include/libkiwix/" +} + +task copyLibkiwixAndroidArm(type: Copy) { + // copying android_arm so file + from buildDir.path + "/libkiwix_android-arm-" + nightly_date_for_libkiwix + '/lib/arm-linux-androideabi/' + into projectDir.path + "/src/main/jniLibs/armeabi-v7a/libkiwix/" +} + +task copyLibkiwixAndroidArm64(type: Copy) { + // copying android_arm64 so file + from buildDir.path + "/libkiwix_android-arm64-" + nightly_date_for_libkiwix + '/lib/aarch64-linux-android/' + into projectDir.path + "/src/main/jniLibs/arm64-v8a/libkiwix/" +} + +task copyLibkiwixAndroidx86(type: Copy) { + // copying android_x86 so file + from buildDir.path + "/libkiwix_android-x86-" + nightly_date_for_libkiwix + '/lib/i686-linux-android/' + into projectDir.path + "/src/main/jniLibs/x86/libkiwix/" +} + +task copyLibkiwixAndroidx86_64(type: Copy) { + // copying android_x86_64 so file + from buildDir.path + "/libkiwix_android-x86_64-" + nightly_date_for_libkiwix + '/lib/x86_64-linux-android/' + into projectDir.path + "/src/main/jniLibs/x86_64/libkiwix/" +} + +task copyLibkiwixLinux_x86_64(type: Copy) { + // copying linux_x86_64 so file + project.ext.set("libkiwix_version", getFileFromFolder(buildDir.path + "/libkiwix_linux-x86_64-" + nightly_date_for_libkiwix + "/lib/x86_64-linux-gnu/")) + from buildDir.path + "/libkiwix_linux-x86_64-" + nightly_date_for_libkiwix + "/lib/x86_64-linux-gnu/" + libkiwix_version + into buildDir.path +} + +static String getFileFromFolder(String path) { + File folderFile = new File(path) + if (folderFile.exists()) { + return folderFile.listFiles() + .stream() + .filter(f -> f.length() > 0) + .collect(Collectors.toList())[0].name + } +} + +task renameLibkiwixSoFile(type: Copy) { + if (libkiwix_version != null) { + from(buildDir.path) + include libkiwix_version + destinationDir file(buildDir.path) + rename libkiwix_version, "libkiwix.so" + } +} + +task copyBuildKiwixSoFile(type: Copy) { + // copying linux_x86_64 so file + from projectDir.path + "/src/androidTests/java/org/kiwix/kiwixlib/libbuildkiwix.so" + into buildDir.path +} + +task createCodeCoverageReport(type: Exec) { + workingDir "${projectDir}/src/androidTests/java/org/kiwix/kiwixlib/" + commandLine 'sh', '-c', "bash 'compile_and_run_test.sh' ${buildDir}/libs/*app*.jar $buildDir" +} + +task checkCurrentJavaVersion() { + if (JavaVersion.current() != JavaVersion.VERSION_11) { + throw new RuntimeException("This build must be run with java 11. your current java version is ${JavaVersion.current()}") + } +} + + +task generateHeaderFilesFromJavaWrapper(type: Exec) { + workingDir "${projectDir}/src/main/java/org/kiwix/" + commandLine 'bash', '-c', "javac -h ${projectDir}/src/main/cpp/include/javah_generated/ -d ${projectDir}/src/androidTests/java/org/kiwix/kiwixlib/ kiwixlib/Book.java kiwixlib/DirectAccessInfo.java kiwixlib/Filter.java kiwixlib/JNIICU.java kiwixlib/JNIKiwixBool.java kiwixlib/JNIKiwixException.java kiwixlib/JNIKiwixInt.java kiwixlib/JNIKiwixReader.java kiwixlib/JNIKiwixSearcher.java kiwixlib/JNIKiwixServer.java kiwixlib/JNIKiwixString.java kiwixlib/Library.java kiwixlib/Manager.java" +} diff --git a/lib/src/main/proguard-rules.pro b/lib/src/main/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/lib/src/main/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/lib/src/main/publish.gradle b/lib/src/main/publish.gradle new file mode 100644 index 0000000..b8e4fb9 --- /dev/null +++ b/lib/src/main/publish.gradle @@ -0,0 +1,83 @@ +apply plugin: 'maven-publish' +apply plugin: 'signing' + +task androidSourcesJar(type: Jar) { + archiveClassifier.set('sources') + if (project.plugins.findPlugin("com.android.library")) { + // For Android libraries + from android.sourceSets.main.java.srcDirs + from android.sourceSets.main.kotlin.srcDirs + } else { + // For pure Kotlin libraries, in case you have them + from sourceSets.main.java.srcDirs + from sourceSets.main.kotlin.srcDirs + } +} + +artifacts { + archives androidSourcesJar +} + +def siteUrl = 'https://www.kiwix.org/en/' +def gitUrl = 'https://github.com/kiwix/libkiwix.git' + +group = GROUP_ID +version = VERSION + +afterEvaluate { + publishing { + publications { + release(MavenPublication) { + + groupId GROUP_ID + artifactId ARTIFACT_ID + version VERSION + + from components.release + + artifact androidSourcesJar + pom { + name = ARTIFACT_ID + description = 'LibKiwix Android library' + url = siteUrl + licenses { + license { + name = 'GPLv3' + url = 'https://www.gnu.org/licenses/gpl-3.0.en.html' + } + } + developers { + developer { + id = 'kiwix' + name = 'kiwix' + email = 'contact@kiwix.org' + } + } + scm { + connection = gitUrl + developerConnection = gitUrl + url = siteUrl + } + } + } + } + repositories { + maven { + url = uri("https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/") + credentials { + username = ossrhUsername + password = ossrhPassword + } + } + } + } +} + +signing { + useInMemoryPgpKeys( + keyId, + key, + password, + ) + sign publishing.publications +} \ No newline at end of file