Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 4 additions & 10 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,23 +1,17 @@
apply plugin: 'java'

buildscript {
repositories {
google()
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.6.0-alpha06'
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
classpath 'com.android.tools.build:gradle:8.7.3'
classpath 'de.undercouch:gradle-download-task:5.6.0'
}
}

allprojects {
repositories {
google()
jcenter()
mavenCentral()
}
}

/*task clean(type: Delete) {
delete rootProject.buildDir
}*/
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
Expand Up @@ -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-5.6-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
76 changes: 29 additions & 47 deletions lib/build.gradle
Original file line number Diff line number Diff line change
@@ -1,75 +1,59 @@
plugins {
id 'de.undercouch.download' version '3.3.0'
id 'com.android.library'
id 'de.undercouch.download'
}

apply plugin: 'com.android.library'
apply plugin: 'de.undercouch.download'
apply plugin: 'com.github.dcendents.android-maven'

group = 'com.github.sevar83'

import de.undercouch.gradle.tasks.download.Download
import org.gradle.internal.os.OperatingSystem;

gradle.projectsEvaluated {
preBuild.dependsOn(buildSqlite)
}
import org.gradle.internal.os.OperatingSystem

android {
compileSdkVersion 29
compileSdk 36
namespace 'org.spatialite'

defaultConfig {
minSdkVersion 16
targetSdkVersion 29
minSdk 21
targetSdk 36
ndkVersion "27.2.12479018"
versionCode 1
versionName project.version
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'proguard-rules.pro'
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}

lintOptions {
abortOnError false
}

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
// ndk gradle support is still very bad so it's built with the regular ndk-build

// ndk-build is invoked manually; disable AGP's built-in JNI source scanning
sourceSets.main.jni.srcDirs = ['src/main/none']
}

dependencies {
implementation 'androidx.core:core:1.0.2'
implementation 'androidx.annotation:annotation:1.1.0'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test:rules:1.2.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
implementation 'androidx.core:core:1.13.1'
implementation 'androidx.annotation:annotation:1.8.2'
androidTestImplementation 'androidx.test:runner:1.6.2'
androidTestImplementation 'androidx.test:rules:1.6.1'
androidTestImplementation 'androidx.test.ext:junit:1.2.1'
}

ext {
sqliteDistributionUrl = 'http://sqlite.org/2016/sqlite-amalgamation-3150100.zip'
}

task sourcesJar(type: Jar) {
classifier = 'sources'
from android.sourceSets.main.java.srcDirs
}

task javadoc(type: Javadoc) {
source = android.sourceSets.main.java.srcDirs
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
classpath += configurations.compile
failOnError false
sqliteDistributionUrl = 'https://sqlite.org/2025/sqlite-amalgamation-3490100.zip'
}

task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from javadoc.destinationDir
gradle.projectsEvaluated {
preBuild.dependsOn(buildSqlite)
}

task downloadSqlite(type: Download) {
Expand All @@ -93,34 +77,32 @@ if (ndkDir == null) {
properties.load(propertiesFile.newDataInputStream())
ndkDir = properties.getProperty('ndk.dir')
if (ndkDir == null) {
throw GradleScriptException("Either NDK_HOME or ndk.dir in local.properties should point to Android NDK!")
throw new GradleException("Either NDK_HOME or ndk.dir in local.properties must point to the Android NDK.")
}
} else {
throw GradleScriptException("Either NDK_HOME or ndk.dir in local.properties should point to Android NDK!")
throw new GradleException("Either NDK_HOME or ndk.dir in local.properties must point to the Android NDK.")
}
}

task buildSqlite(dependsOn: installSqlite, type: Exec) {
println("NDK directory: $ndkDir")

// Add NDK_DEBUG=1 for debug symbols or V=1 for verbose building output
if (OperatingSystem.current().linux) {
commandLine "$ndkDir/ndk-build", '-j8', '-C', file('src/main/jni').absolutePath
} else if (OperatingSystem.current().windows) {
commandLine "$ndkDir/ndk-build.cmd", '-j8', '-C', file('src/main/jni').absolutePath
} else {
throw GradleScriptException("Unsupported OS")
throw new GradleException("Unsupported OS: ${OperatingSystem.current()}")
}
}

task ndkClean(type: Exec, description: 'Clean NDK Binaries') {
task ndkClean(type: Exec, description: 'Clean NDK binaries') {
if (OperatingSystem.current().linux) {
commandLine "$ndkDir/ndk-build", 'clean', '-C', file('src/main/jni').absolutePath
} else if (OperatingSystem.current().windows) {
commandLine "$ndkDir/ndk-build.cmd", 'clean', '-C', file('src/main/jni').absolutePath
} else {
throw GradleScriptException("Unsupported OS")
throw new GradleException("Unsupported OS: ${OperatingSystem.current()}")
}
}

clean.dependsOn 'ndkClean'
clean.dependsOn 'ndkClean'
15 changes: 7 additions & 8 deletions lib/src/main/jni/Application.mk
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
APP_STL := c++_shared
APP_OPTIM := release
APP_ABI := armeabi-v7a,arm64-v8a,x86,x86_64
APP_PLATFORM := android-16
APP_STL := c++_static
APP_OPTIM := release
APP_ABI := armeabi-v7a arm64-v8a x86_64
APP_PLATFORM := android-21
NDK_TOOLCHAIN_VERSION := clang
NDK_APP_LIBS_OUT=../jniLibs
# Temp workaround for https://github.com/android-ndk/ndk/issues/332
APP_DEPRECATED_HEADERS := true
APP_SHORT_COMMANDS := true
NDK_APP_LIBS_OUT := ../jniLibs
# Use response files to avoid Windows command-line length limit (Error 87 from llvm-ar)
NDK_APP_SHORT_COMMANDS := true
52 changes: 37 additions & 15 deletions lib/src/main/jni/android_database_SQLiteConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "CursorWindow.h"

#include <string>
#include <mutex>

#include <spatialite.h>

Expand All @@ -54,6 +55,31 @@ static const int BUSY_TIMEOUT_MS = 2500;

static JavaVM *gpJavaVM = 0;

// ---------------------------------------------------------------------------
// Lazy JNI registration
//
// JNI_OnLoad fires on the Mono bootstrap thread, which holds the *system*
// class loader. FindClass("org/spatialite/...") therefore returns null and
// the subsequent LOG_FATAL_IF aborts the process (SIGABRT).
//
// Fix: skip all RegisterNatives in JNI_OnLoad; call them once from nativeOpen()
// which always runs on a Java application thread that owns the app class loader.
// ---------------------------------------------------------------------------
static std::once_flag g_jni_register_once;
// Forward declarations (definitions are near the bottom of this file / other TUs)
static int register_android_database_SQLiteConnection(JNIEnv *env);
extern int register_android_database_SQLiteGlobal(JNIEnv *env);
extern int register_android_database_SQLiteDebug(JNIEnv *env);
extern int register_android_database_CursorWindow(JNIEnv *env);

static void doLazyRegisterAll(JNIEnv* env) {
register_android_database_SQLiteConnection(env);
register_android_database_SQLiteDebug(env);
register_android_database_SQLiteGlobal(env);
register_android_database_CursorWindow(env);
}
// ---------------------------------------------------------------------------

static struct {
jfieldID name;
jfieldID numArgs;
Expand Down Expand Up @@ -134,6 +160,10 @@ static int coll_localized(

static jlong nativeOpen(JNIEnv* env, jclass clazz, jstring pathStr, jint openFlags,
jstring labelStr, jboolean enableTrace, jboolean enableProfile) {
// Ensure all four JNI native-method tables are registered exactly once, on
// an app thread so FindClass resolves against the app class loader.
std::call_once(g_jni_register_once, doLazyRegisterAll, env);

int sqliteFlags;
if (openFlags & SQLiteConnection::CREATE_IF_NECESSARY) {
sqliteFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
Expand Down Expand Up @@ -930,7 +960,8 @@ static JNINativeMethod sMethods[] =
int register_android_database_SQLiteConnection(JNIEnv *env)
{
jclass clazz;
FIND_CLASS(clazz, "org/spatialite/database/SQLiteCustomFunction");
clazz = env->FindClass("org/spatialite/database/SQLiteCustomFunction");
LOG_FATAL_IF(!clazz, "Unable to find class org/spatialite/database/SQLiteCustomFunction");

GET_FIELD_ID(gSQLiteCustomFunctionClassInfo.name, clazz,
"name", "Ljava/lang/String;");
Expand All @@ -939,7 +970,8 @@ int register_android_database_SQLiteConnection(JNIEnv *env)
GET_METHOD_ID(gSQLiteCustomFunctionClassInfo.dispatchCallback,
clazz, "dispatchCallback", "([Ljava/lang/String;)Ljava/lang/String;");

FIND_CLASS(clazz, "java/lang/String");
clazz = env->FindClass("java/lang/String");
LOG_FATAL_IF(!clazz, "Unable to find class java/lang/String");
gStringClassInfo.clazz = jclass(env->NewGlobalRef(clazz));

return jniRegisterNativeMethods(env,
Expand All @@ -948,23 +980,13 @@ int register_android_database_SQLiteConnection(JNIEnv *env)
);
}

extern int register_android_database_SQLiteGlobal(JNIEnv *env);
extern int register_android_database_SQLiteDebug(JNIEnv *env);
extern int register_android_database_CursorWindow(JNIEnv *env);

} // namespace android

extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv *env = 0;

// Only save the VM pointer here. All RegisterNatives calls happen lazily
// from nativeOpen() (the first native call on an app thread) so that
// FindClass resolves against the app class loader, not the bootstrap loader.
android::gpJavaVM = vm;
vm->GetEnv((void**)&env, JNI_VERSION_1_4);

android::register_android_database_SQLiteConnection(env);
android::register_android_database_SQLiteDebug(env);
android::register_android_database_SQLiteGlobal(env);
android::register_android_database_CursorWindow(env);

return JNI_VERSION_1_4;
}

Expand Down
2 changes: 1 addition & 1 deletion lib/src/main/jni/ndk-modules/freexl/freexl-1.0.2.mk
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ LOCAL_MODULE := freexl
FREEXL_FILES := \
${FREEXL_PATH}/src/freexl.c

LOCAL_CFLAGS += -fvisibility=hidden
LOCAL_CFLAGS += -fvisibility=hidden -Wno-int-conversion -Wno-implicit-function-declaration

LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/$(FREEXL_PATH) \
Expand Down
6 changes: 6 additions & 0 deletions lib/src/main/jni/ndk-modules/geos/geos-3.4.2.mk
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,12 @@ LOCAL_SRC_FILES := \
$(GEOS_FILES) \
src-io-CLocalizer.cpp

# GEOS 3.4.2 uses std::auto_ptr which was removed in C++17.
# Force C++14 for this module so it compiles with NDK r21+.
LOCAL_CPPFLAGS += -std=c++14
# Use response files to avoid Windows command-line length limit (Error 87 from llvm-ar).
LOCAL_SHORT_COMMANDS := true

TARGET-process-src-files-tags += $(call add-src-files-target-cflags, \
geos/src/io/WKTReader.cpp, -include cctype)

Expand Down
2 changes: 2 additions & 0 deletions lib/src/main/jni/ndk-modules/libiconv/libiconv-1.13.mk
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ LOCAL_MODULE := iconv

LOCAL_CFLAGS := \
-Wno-multichar \
-Wno-int-conversion \
-Wno-implicit-function-declaration \
-D_ANDROID \
-DLIBDIR "$(LOCAL_PATH)/$(ICONV_PATH)/libcharset/lib" \
-DBUILDING_LIBICONV \
Expand Down
4 changes: 3 additions & 1 deletion lib/src/main/jni/ndk-modules/liblzma/xz-5.2.1.mk
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ LOCAL_MODULE := liblzma
lzma_flags := \
-DHAVE_CONFIG_H \
-g -O2 \
-std=gnu99
-std=gnu99 \
-Wno-int-conversion \
-Wno-implicit-function-declaration

LOCAL_CFLAGS := \
$(lzma_flags)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,9 @@ spatialite_flags := \

LOCAL_CFLAGS := \
$(common_sqlite_flags) \
$(spatialite_flags)
$(spatialite_flags) \
-Wno-int-conversion \
-Wno-implicit-function-declaration

LOCAL_STATIC_LIBRARIES := proj4 geos libsqlite3x iconv libxml2 freexl

Expand Down
4 changes: 3 additions & 1 deletion lib/src/main/jni/ndk-modules/libxml2/libxml2-2.9.2.mk
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ xml2_flags := \
-DLIBXML_THREAD_ENABLED=1

LOCAL_CFLAGS := \
$(xml2_flags)
$(xml2_flags) \
-Wno-int-conversion \
-Wno-implicit-function-declaration

LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/$(XML2_PATH)/include \
Expand Down
2 changes: 1 addition & 1 deletion lib/src/main/jni/ndk-modules/proj.4/proj-4.8.0.mk
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ LOCAL_MODULE := proj4

PROJ4_CONFIG := $(LOCAL_PATH)/config

LOCAL_CFLAGS += -fvisibility=hidden
LOCAL_CFLAGS += -fvisibility=hidden -Wno-int-conversion -Wno-implicit-function-declaration
LOCAL_C_INCLUDES := $(LOCAL_PATH)/$(PROJ4_PATH)/proj/src $(PROJ4_CONFIG)
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/$(PROJ4_PATH)/proj/src $(PROJ4_CONFIG)
LOCAL_SRC_FILES := \
Expand Down
Loading