From 3bd5fc7463dbc7dadac93482d5fcc9b3c07a77d4 Mon Sep 17 00:00:00 2001 From: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com> Date: Sat, 1 Jul 2023 22:44:36 +0300 Subject: [PATCH] multiplatform: moved to Gradle KTS and common directory structure (#2633) * multiplatform: moved to Gradle KTS and common directory structure * renamed for review * different versions for Android and desktop * update desktop version_name * Revert "renamed for review" This reverts commit 80041efe40faf3c5606685143d143a253ca98ac9. * EOLs * change version to 1.0 to appease linter --------- Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com> --- apps/multiplatform/.gitignore | 1 - apps/multiplatform/android/build.gradle | 243 -- apps/multiplatform/android/build.gradle.kts | 210 ++ .../java/chat/simplex/app/ui/theme/Theme.kt | 3 +- .../chat/simplex/app/ui/theme/ThemeManager.kt | 3 +- .../simplex/app/views/chat/ComposeView.kt | 2 +- .../app/views/chat/item/FramedItemView.kt | 3 +- .../app/views/helpers/GestureDetector.kt | 21 +- apps/multiplatform/build.gradle | 50 - apps/multiplatform/build.gradle.kts | 73 + apps/multiplatform/common/build.gradle.kts | 140 ++ .../src/androidMain/AndroidManifest.xml | 4 + .../commonMain/cpp/android}/CMakeLists.txt | 2 +- .../src/commonMain/cpp/android}/simplex-api.c | 0 .../src/commonMain/cpp/desktop/CMakeLists.txt | 92 + .../src/commonMain/cpp/desktop/include/jni.h | 2001 +++++++++++++++++ .../cpp/desktop/include/unix/jni_md.h | 66 + .../cpp/desktop/include/windows/jni_md.h | 40 + .../src/commonMain/cpp/desktop/simplex-api.c | 98 + .../toolchains/aarch64-linux-gnu-gcc.cmake | 20 + .../aarch64-mac-apple-darwin-gcc.cmake | 17 + .../toolchains/x86_64-linux-gnu-gcc.cmake | 17 + .../x86_64-mac-apple-darwin-gcc.cmake | 17 + .../x86_64-windows-mingw32-gcc.cmake | 17 + apps/multiplatform/desktop/build.gradle.kts | 169 ++ apps/multiplatform/gradle.properties | 10 + .../gradle/wrapper/gradle-wrapper.properties | 2 +- apps/multiplatform/settings.gradle | 17 - apps/multiplatform/settings.gradle.kts | 21 + scripts/android/build-android-bundle.sh | 6 +- scripts/android/build-android.sh | 6 +- scripts/android/download-libs.sh | 2 +- scripts/android/prepare.sh | 16 +- 33 files changed, 3042 insertions(+), 347 deletions(-) delete mode 100644 apps/multiplatform/android/build.gradle create mode 100644 apps/multiplatform/android/build.gradle.kts delete mode 100644 apps/multiplatform/build.gradle create mode 100644 apps/multiplatform/build.gradle.kts create mode 100644 apps/multiplatform/common/build.gradle.kts create mode 100644 apps/multiplatform/common/src/androidMain/AndroidManifest.xml rename apps/multiplatform/{android/src/main/cpp => common/src/commonMain/cpp/android}/CMakeLists.txt (99%) rename apps/multiplatform/{android/src/main/cpp => common/src/commonMain/cpp/android}/simplex-api.c (100%) create mode 100644 apps/multiplatform/common/src/commonMain/cpp/desktop/CMakeLists.txt create mode 100644 apps/multiplatform/common/src/commonMain/cpp/desktop/include/jni.h create mode 100644 apps/multiplatform/common/src/commonMain/cpp/desktop/include/unix/jni_md.h create mode 100644 apps/multiplatform/common/src/commonMain/cpp/desktop/include/windows/jni_md.h create mode 100644 apps/multiplatform/common/src/commonMain/cpp/desktop/simplex-api.c create mode 100644 apps/multiplatform/common/src/commonMain/cpp/desktop/toolchains/aarch64-linux-gnu-gcc.cmake create mode 100644 apps/multiplatform/common/src/commonMain/cpp/desktop/toolchains/aarch64-mac-apple-darwin-gcc.cmake create mode 100644 apps/multiplatform/common/src/commonMain/cpp/desktop/toolchains/x86_64-linux-gnu-gcc.cmake create mode 100644 apps/multiplatform/common/src/commonMain/cpp/desktop/toolchains/x86_64-mac-apple-darwin-gcc.cmake create mode 100644 apps/multiplatform/common/src/commonMain/cpp/desktop/toolchains/x86_64-windows-mingw32-gcc.cmake create mode 100644 apps/multiplatform/desktop/build.gradle.kts delete mode 100644 apps/multiplatform/settings.gradle create mode 100644 apps/multiplatform/settings.gradle.kts diff --git a/apps/multiplatform/.gitignore b/apps/multiplatform/.gitignore index 5012dd182..d8419431d 100644 --- a/apps/multiplatform/.gitignore +++ b/apps/multiplatform/.gitignore @@ -12,7 +12,6 @@ local.properties common/src/commonMain/cpp/android/libs/ common/src/commonMain/cpp/desktop/libs/ common/src/commonMain/resources/libs/ -android/src/main/cpp/libs/ android/build android/release common/build diff --git a/apps/multiplatform/android/build.gradle b/apps/multiplatform/android/build.gradle deleted file mode 100644 index b483f6cf4..000000000 --- a/apps/multiplatform/android/build.gradle +++ /dev/null @@ -1,243 +0,0 @@ -plugins { - id 'com.android.application' - id 'org.jetbrains.kotlin.android' - id 'org.jetbrains.kotlin.plugin.serialization' -} - -android { - compileSdk 33 - - defaultConfig { - applicationId "chat.simplex.app" - minSdk 26 - targetSdk 33 - // !!! - // skip version code after release to F-Droid, as it uses two version codes - versionCode 129 - versionName "5.2-beta.0" - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - vectorDrawables { - useSupportLibrary true - } - externalNativeBuild { - cmake { - cppFlags '' - } - } - manifestPlaceholders.app_name = "@string/app_name" - manifestPlaceholders.provider_authorities = "chat.simplex.app.provider" - manifestPlaceholders.extract_native_libs = compression_level != "0" - } - - buildTypes { - debug { - applicationIdSuffix "$application_id_suffix" - debuggable new Boolean("$enable_debuggable") - manifestPlaceholders.app_name = "$app_name" - // Provider can't be the same for different apps on the same device - manifestPlaceholders.provider_authorities = "chat.simplex.app${application_id_suffix}.provider" - } - 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' - freeCompilerArgs += "-opt-in=kotlinx.coroutines.DelicateCoroutinesApi" - freeCompilerArgs += "-opt-in=androidx.compose.foundation.ExperimentalFoundationApi" - freeCompilerArgs += "-opt-in=androidx.compose.ui.text.ExperimentalTextApi" - freeCompilerArgs += "-opt-in=androidx.compose.material.ExperimentalMaterialApi" - freeCompilerArgs += "-opt-in=com.google.accompanist.insets.ExperimentalAnimatedInsets" - freeCompilerArgs += "-opt-in=com.google.accompanist.permissions.ExperimentalPermissionsApi" - freeCompilerArgs += "-opt-in=kotlinx.serialization.InternalSerializationApi" - freeCompilerArgs += "-opt-in=kotlinx.serialization.ExperimentalSerializationApi" - } - externalNativeBuild { - cmake { - path file('src/main/cpp/CMakeLists.txt') - } - } - buildFeatures { - compose true - } - composeOptions { - kotlinCompilerExtensionVersion compose_version - } - packagingOptions { - resources { - excludes += '/META-INF/{AL2.0,LGPL2.1}' - } - jniLibs.useLegacyPackaging = compression_level != "0" - } - def isRelease = gradle.getStartParameter().taskNames.find({ it.toLowerCase().contains("release") }) != null - def isBundle = gradle.getStartParameter().taskNames.find({ it.toLowerCase().contains("bundle") }) != null -// if (isRelease) { - // Comma separated list of languages that will be included in the apk - android.defaultConfig.resConfigs( - "en", - "cs", - "de", - "es", - "fr", - "it", - "ja", - "nl", - "pl", - "pt-rBR", - "ru", - "zh-rCN" - ) -// } - if (isBundle) { - defaultConfig.ndk.abiFilters 'arm64-v8a', 'armeabi-v7a' - } else { - splits { - abi { - enable true - reset() - if (isRelease) { - include 'arm64-v8a', 'armeabi-v7a' - } else { - include 'arm64-v8a', 'armeabi-v7a' - universalApk false - } - } - } - } -} - -dependencies { - implementation 'androidx.core:core-ktx:1.7.0' - implementation "androidx.compose.ui:ui:$compose_version" - implementation "androidx.compose.material:material:$compose_version" - implementation "androidx.compose.ui:ui-tooling-preview:$compose_version" - implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.1' - implementation 'androidx.lifecycle:lifecycle-process:2.4.1' - implementation 'androidx.activity:activity-compose:1.4.0' - implementation 'androidx.fragment:fragment:1.4.1' - implementation 'org.jetbrains.kotlinx:kotlinx-datetime:0.3.2' - implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2' - implementation 'com.charleskorn.kaml:kaml:0.43.0' - //implementation "androidx.compose.material:material-icons-extended:$compose_version" - implementation "androidx.compose.ui:ui-util:$compose_version" - implementation "androidx.navigation:navigation-compose:2.4.1" - implementation "com.google.accompanist:accompanist-insets:0.23.0" - implementation 'androidx.webkit:webkit:1.4.0' - implementation "com.godaddy.android.colorpicker:compose-color-picker:0.4.2" - - def work_version = "2.7.1" - implementation "androidx.work:work-runtime-ktx:$work_version" - implementation "androidx.work:work-multiprocess:$work_version" - - def camerax_version = "1.1.0-beta01" - implementation "androidx.camera:camera-core:${camerax_version}" - implementation "androidx.camera:camera-camera2:${camerax_version}" - implementation "androidx.camera:camera-lifecycle:${camerax_version}" - implementation "androidx.camera:camera-view:${camerax_version}" - - //Barcode - implementation 'org.boofcv:boofcv-android:0.40.1' - implementation 'org.boofcv:boofcv-core:0.40.1' - - //Camera Permission - implementation "com.google.accompanist:accompanist-permissions:0.23.0" - implementation "com.google.accompanist:accompanist-pager:0.25.1" - - // Link Previews - implementation 'org.jsoup:jsoup:1.13.1' - - // Biometric authentication - implementation 'androidx.biometric:biometric:1.2.0-alpha04' - - // GIFs support - implementation "io.coil-kt:coil-compose:2.1.0" - implementation "io.coil-kt:coil-gif:2.1.0" - - // Video support - implementation "com.google.android.exoplayer:exoplayer:2.17.1" - - // Wheel picker - implementation 'com.github.zj565061763:compose-wheel-picker:1.0.0-alpha10' - - testImplementation 'junit:junit:4.13.2' - androidTestImplementation 'androidx.test.ext:junit:1.1.3' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' - androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version" - debugImplementation "androidx.compose.ui:ui-tooling:$compose_version" - implementation "com.jakewharton:process-phoenix:2.1.2" -} - -// Don't do anything if no compression is needed -if (compression_level != "0") { - tasks.whenTaskAdded { task -> - if (task.name == 'packageDebug') { - task.finalizedBy compressApk - } else if (task.name == 'packageRelease') { - task.finalizedBy compressApk - } - } -} - -tasks.register("compressApk") { - doLast { - def isRelease = gradle.getStartParameter().taskNames.find({ it.toLowerCase().contains("release") }) != null - def buildType - if (isRelease) { - buildType = "release" - } else { - buildType = "debug" - } - def javaHome = System.properties['java.home'] ?: org.gradle.internal.jvm.Jvm.current().getJavaHome() - def sdkDir = android.getSdkDirectory().getAbsolutePath() - def keyAlias = "" - def keyPassword = "" - def storeFile = "" - def storePassword = "" - if (project.properties['android.injected.signing.key.alias'] != null) { - keyAlias = project.properties['android.injected.signing.key.alias'] - keyPassword = project.properties['android.injected.signing.key.password'] - storeFile = project.properties['android.injected.signing.store.file'] - storePassword = project.properties['android.injected.signing.store.password'] - } else if (android.signingConfigs.hasProperty(buildType)) { - def gradleConfig = android.signingConfigs[buildType] - keyAlias = gradleConfig.keyAlias - keyPassword = gradleConfig.keyPassword - storeFile = gradleConfig.storeFile - storePassword = gradleConfig.storePassword - } else { - // There is no signing config for current build type, can't sign the apk - println("No signing configs for this build type: $buildType") - return - } - - def outputDir = tasks["package${buildType.capitalize()}"].outputs.files.last() - - exec { - workingDir '../../../scripts/android' - setEnvironment(['JAVA_HOME': "$javaHome"]) - commandLine './compress-and-sign-apk.sh', \ - "$compression_level", \ - "$outputDir", \ - "$sdkDir", \ - "$storeFile", \ - "$storePassword", \ - "$keyAlias", \ - "$keyPassword" - } - - if (project.properties['android.injected.signing.key.alias'] != null && buildType == 'release') { - new File(outputDir, "android-release.apk").renameTo(new File(outputDir, "simplex.apk")) - new File(outputDir, "android-armeabi-v7a-release.apk").renameTo(new File(outputDir, "simplex-armv7a.apk")) - new File(outputDir, "android-arm64-v8a-release.apk").renameTo(new File(outputDir, "simplex.apk")) - } - - // View all gradle properties set - // project.properties.each { k, v -> println "$k -> $v" } - } -} diff --git a/apps/multiplatform/android/build.gradle.kts b/apps/multiplatform/android/build.gradle.kts new file mode 100644 index 000000000..5d54c5f7b --- /dev/null +++ b/apps/multiplatform/android/build.gradle.kts @@ -0,0 +1,210 @@ +@file:Suppress("UnstableApiUsage") + +plugins { + id("com.android.application") + id("org.jetbrains.compose") + kotlin("android") + id("org.jetbrains.kotlin.plugin.serialization") +} + +repositories { + maven("https://jitpack.io") +} + +android { + compileSdkVersion(33) + + defaultConfig { + applicationId = "chat.simplex.app" + minSdkVersion(26) + targetSdkVersion(33) + // !!! + // skip version code after release to F-Droid, as it uses two version codes + versionCode = (extra["android.version_code"] as String).toInt() + versionName = extra["android.version_name"] as String + + testInstrumentationRunner = "android.support.test.runner.AndroidJUnitRunner" + vectorDrawables { + useSupportLibrary = true + } + externalNativeBuild { + cmake { + cppFlags("") + } + } + manifestPlaceholders["app_name"] = "@string/app_name" + manifestPlaceholders["provider_authorities"] = "chat.simplex.app.provider" + manifestPlaceholders["extract_native_libs"] = rootProject.extra["compression.level"] as Int != 0 + } + + buildTypes { + debug { + applicationIdSuffix = rootProject.extra["application_id.suffix"] as String + isDebuggable = rootProject.extra["enable_debuggable"] as Boolean + manifestPlaceholders["app_name"] = rootProject.extra["app.name"] as String + // Provider can"t be the same for different apps on the same device + manifestPlaceholders["provider_authorities"] = "chat.simplex.app${rootProject.extra["application_id.suffix"]}.provider" + } + release { + isMinifyEnabled = 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" + freeCompilerArgs += "-opt-in=kotlinx.coroutines.DelicateCoroutinesApi" + freeCompilerArgs += "-opt-in=androidx.compose.foundation.ExperimentalFoundationApi" + freeCompilerArgs += "-opt-in=androidx.compose.ui.text.ExperimentalTextApi" + freeCompilerArgs += "-opt-in=androidx.compose.material.ExperimentalMaterialApi" + freeCompilerArgs += "-opt-in=com.google.accompanist.insets.ExperimentalAnimatedInsets" + freeCompilerArgs += "-opt-in=com.google.accompanist.permissions.ExperimentalPermissionsApi" + freeCompilerArgs += "-opt-in=kotlinx.serialization.InternalSerializationApi" + freeCompilerArgs += "-opt-in=kotlinx.serialization.ExperimentalSerializationApi" + } + externalNativeBuild { + cmake { + path(File("../common/src/commonMain/cpp/android/CMakeLists.txt")) + } + } + buildTypes { + getByName("release") { + isMinifyEnabled = false + } + } + packagingOptions { + resources { + excludes += "/META-INF/{AL2.0,LGPL2.1}" + } + jniLibs.useLegacyPackaging = rootProject.extra["compression.level"] as Int != 0 + } + val isRelease = gradle.startParameter.taskNames.find { it.toLowerCase().contains("release") } != null + val isBundle = gradle.startParameter.taskNames.find { it.toLowerCase().contains("bundle") } != null + // if (isRelease) { + // Comma separated list of languages that will be included in the apk + android.defaultConfig.resConfigs( + "en", + "cs", + "de", + "es", + "fr", + "it", + "ja", + "nl", + "pl", + "pt-rBR", + "ru", + "zh-rCN" + ) + // } + if (isBundle) { + defaultConfig.ndk.abiFilters("arm64-v8a", "armeabi-v7a") + } else { + splits { + abi { + isEnable = true + reset() + if (isRelease) { + include("arm64-v8a", "armeabi-v7a") + } else { + include("arm64-v8a", "armeabi-v7a") + isUniversalApk = false + } + } + } + } +} + +dependencies { + implementation(project(":common")) + implementation("androidx.core:core-ktx:1.7.0") + //implementation("androidx.compose.ui:ui:${rootProject.extra["compose.version"] as String}") + //implementation("androidx.compose.material:material:$compose_version") + //implementation("androidx.compose.ui:ui-tooling-preview:$compose_version") + implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.4.1") + implementation("androidx.lifecycle:lifecycle-process:2.4.1") + implementation("androidx.activity:activity-compose:1.5.0") + //implementation("androidx.compose.material:material-icons-extended:$compose_version") + //implementation("androidx.compose.ui:ui-util:$compose_version") + + implementation("com.google.accompanist:accompanist-pager:0.25.1") + + testImplementation("junit:junit:4.13.2") + androidTestImplementation("androidx.test.ext:junit:1.1.3") + androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0") + //androidTestImplementation("androidx.compose.ui:ui-test-junit4:$compose_version") + debugImplementation("androidx.compose.ui:ui-tooling:${rootProject.extra["compose.version"] as String}") +} + +tasks { + val compressApk by creating { + doLast { + val isRelease = gradle.startParameter.taskNames.find { it.toLowerCase().contains("release") } != null + val buildType: String = if (isRelease) "release" else "debug" + val javaHome = System.getProperties()["java.home"] ?: org.gradle.internal.jvm.Jvm.current().javaHome + val sdkDir = android.sdkDirectory.absolutePath + var keyAlias = "" + var keyPassword = "" + var storeFile = "" + var storePassword = "" + if (project.properties["android.injected.signing.key.alias"] != null) { + keyAlias = project.properties["android.injected.signing.key.alias"] as String + keyPassword = project.properties["android.injected.signing.key.password"] as String + storeFile = project.properties["android.injected.signing.store.file"] as String + storePassword = project.properties["android.injected.signing.store.password"] as String + } else { + try { + val gradleConfig = android.signingConfigs.getByName(buildType) + keyAlias = gradleConfig.keyAlias!! + keyPassword = gradleConfig.keyPassword!! + storeFile = gradleConfig.storeFile!!.absolutePath + storePassword = gradleConfig.storePassword!! + } catch (e: UnknownDomainObjectException) { + // There is no signing config for current build type, can"t sign the apk + println("No signing configs for this build type: $buildType") + return@doLast + } + } + lateinit var outputDir: File + named(if (isRelease) "packageRelease" else "packageDebug") { + outputDir = outputs.files.files.last() + } + exec { + workingDir("../../../scripts/android") + setEnvironment(mapOf("JAVA_HOME" to "$javaHome")) + commandLine = listOf( + "./compress-and-sign-apk.sh", + "${rootProject.extra["compression.level"]}", + "$outputDir", + "$sdkDir", + "$storeFile", + "$storePassword", + "$keyAlias", + "$keyPassword" + ) + } + + if (project.properties["android.injected.signing.key.alias"] != null && buildType == "release") { + File(outputDir, "android-release.apk").renameTo(File(outputDir, "simplex.apk")) + File(outputDir, "android-armeabi-v7a-release.apk").renameTo(File(outputDir, "simplex-armv7a.apk")) + File(outputDir, "android-arm64-v8a-release.apk").renameTo(File(outputDir, "simplex.apk")) + } + // View all gradle properties set + // project.properties.each { k, v -> println "$k -> $v" } + } + } + + // Don"t do anything if no compression is needed + if (rootProject.extra["compression.level"] as Int != 0) { + whenTaskAdded { + if (name == "packageDebug") { + finalizedBy(compressApk) + } else if (name == "packageRelease") { + finalizedBy(compressApk) + } + } + } +} diff --git a/apps/multiplatform/android/src/main/java/chat/simplex/app/ui/theme/Theme.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/ui/theme/Theme.kt index 24652c76f..8f1ec7eab 100644 --- a/apps/multiplatform/android/src/main/java/chat/simplex/app/ui/theme/Theme.kt +++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/ui/theme/Theme.kt @@ -16,7 +16,6 @@ import chat.simplex.app.views.helpers.* import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable -import okhttp3.internal.toHexString enum class DefaultTheme { SYSTEM, LIGHT, DARK, SIMPLEX; @@ -150,7 +149,7 @@ data class ThemeColors( private fun String.colorFromReadableHex(): Color = Color(this.replace("#", "").toLongOrNull(16) ?: Color.White.toArgb().toLong()) -private fun Color.toReadableHex(): String = "#" + toArgb().toHexString() +private fun Color.toReadableHex(): String = "#" + Integer.toHexString(toArgb()) @Serializable data class ThemeOverrides ( diff --git a/apps/multiplatform/android/src/main/java/chat/simplex/app/ui/theme/ThemeManager.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/ui/theme/ThemeManager.kt index 3453dad7e..b7df77b0a 100644 --- a/apps/multiplatform/android/src/main/java/chat/simplex/app/ui/theme/ThemeManager.kt +++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/ui/theme/ThemeManager.kt @@ -7,7 +7,6 @@ import chat.simplex.app.R import chat.simplex.app.SimplexApp import chat.simplex.app.model.AppPreferences import chat.simplex.app.views.helpers.generalGetString -import okhttp3.internal.toHexString object ThemeManager { private val appPrefs: AppPreferences by lazy { @@ -149,4 +148,4 @@ object ThemeManager { } } -private fun Color.toReadableHex(): String = "#" + toArgb().toHexString() +private fun Color.toReadableHex(): String = "#" + Integer.toHexString(toArgb()) diff --git a/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/ComposeView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/ComposeView.kt index 189a8e4ad..ffdb4afa8 100644 --- a/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/ComposeView.kt +++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/ComposeView.kt @@ -594,7 +594,7 @@ fun ComposeView( suspend fun sendLiveMessage() { val cs = composeState.value val typedMsg = cs.message - if ((cs.sendEnabled() || cs.contextItem is ComposeContextItem.QuotedItem) && (cs.liveMessage == null || !cs.liveMessage?.sent)) { + if ((cs.sendEnabled() || cs.contextItem is ComposeContextItem.QuotedItem) && (cs.liveMessage == null || !cs.liveMessage.sent)) { val ci = sendMessageAsync(typedMsg, live = true, ttl = null) if (ci != null) { composeState.value = composeState.value.copy(liveMessage = LiveMessage(ci, typedMsg = typedMsg, sentMsg = typedMsg, sent = true)) diff --git a/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/FramedItemView.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/FramedItemView.kt index 61d8080e0..d81b7943b 100644 --- a/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/FramedItemView.kt +++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/chat/item/FramedItemView.kt @@ -21,7 +21,6 @@ import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.* import androidx.compose.ui.unit.* -import androidx.compose.ui.util.fastMap import chat.simplex.app.R import chat.simplex.app.model.* import chat.simplex.app.ui.theme.* @@ -300,7 +299,7 @@ fun PriorityLayout( // Find important element which should tell what max width other elements can use // Expecting only one such element. Can be less than one but not more val imagePlaceable = measureable.firstOrNull { it.layoutId == priorityLayoutId }?.measure(constraints) - val placeables: List = measureable.fastMap { + val placeables: List = measureable.map { if (it.layoutId == priorityLayoutId) imagePlaceable!! else diff --git a/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/GestureDetector.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/GestureDetector.kt index 463d0eacb..daf323dc0 100644 --- a/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/GestureDetector.kt +++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/views/helpers/GestureDetector.kt @@ -28,9 +28,6 @@ import androidx.compose.ui.geometry.Offset import androidx.compose.ui.input.pointer.* import androidx.compose.ui.platform.LocalViewConfiguration import androidx.compose.ui.unit.Density -import androidx.compose.ui.util.fastAll -import androidx.compose.ui.util.fastAny -import androidx.compose.ui.util.fastForEach import chat.simplex.app.TAG import kotlinx.coroutines.* import kotlinx.coroutines.sync.Mutex @@ -98,8 +95,8 @@ suspend fun PointerInputScope.detectGesture( private suspend fun AwaitPointerEventScope.consumeUntilUp() { do { val event = awaitPointerEvent() - event.changes.fastForEach { it.consumeAllChanges() } - } while (event.changes.fastAny { it.pressed }) + event.changes.forEach { it.consumeAllChanges() } + } while (event.changes.any { it.pressed }) } suspend fun AwaitPointerEventScope.awaitFirstDown( @@ -115,7 +112,7 @@ internal suspend fun AwaitPointerEventScope.awaitFirstDownOnPass( do { event = awaitPointerEvent(pass) } while ( - !event.changes.fastAll { + !event.changes.all { if (requireUnconsumed) it.changedToDown() else it.changedToDownIgnoreConsumed() } ) @@ -125,18 +122,18 @@ internal suspend fun AwaitPointerEventScope.awaitFirstDownOnPass( suspend fun AwaitPointerEventScope.waitForUpOrCancellation(): PointerInputChange? { while (true) { val event = awaitPointerEvent(PointerEventPass.Main) - if (event.changes.fastAll { it.changedToUp() }) { + if (event.changes.all { it.changedToUp() }) { return event.changes[0] } - if (event.changes.fastAny { + if (event.changes.any { it.consumed.downChange || it.isOutOfBounds(size, extendedTouchPadding) } ) { return null } val consumeCheck = awaitPointerEvent(PointerEventPass.Final) - if (consumeCheck.changes.fastAny { it.positionChangeConsumed() }) { + if (consumeCheck.changes.any { it.positionChangeConsumed() }) { return null } } @@ -254,7 +251,7 @@ suspend fun PointerInputScope.detectTransformGestures( awaitFirstDown(requireUnconsumed = false) do { val event = awaitPointerEvent() - val canceled = event.changes.fastAny { it.isConsumed } + val canceled = event.changes.any { it.isConsumed } if (!canceled) { val zoomChange = event.calculateZoom() val rotationChange = event.calculateRotation() @@ -288,14 +285,14 @@ suspend fun PointerInputScope.detectTransformGestures( ) { onGesture(centroid, panChange, zoomChange, effectiveRotation) } - event.changes.fastForEach { + event.changes.forEach { if (it.positionChanged() && zoom != 1f && allowIntercept()) { it.consume() } } } } - } while (!canceled && event.changes.fastAny { it.pressed }) + } while (!canceled && event.changes.any { it.pressed }) } } } diff --git a/apps/multiplatform/build.gradle b/apps/multiplatform/build.gradle deleted file mode 100644 index 08dbb3f98..000000000 --- a/apps/multiplatform/build.gradle +++ /dev/null @@ -1,50 +0,0 @@ -buildscript { - Properties localProperties = new Properties() - if (rootProject.file('local.properties').canRead()) { - localProperties.load(rootProject.file("local.properties").newDataInputStream()) - } - - ext { - compose_version = localProperties['compose_version'] ?: '1.2.0-beta02' - kotlin_version = localProperties['kotlin_version'] ?: '1.6.21' - gradle_plugin_version = localProperties['gradle_plugin_version'] ?: '7.2.0' - abi_filter = localProperties['abi_filter'] ?: 'arm64-v8a' - - // Name that will be shown for debug build. By default it is from strings - app_name = localProperties['app_name'] ?: "@string/app_name" - // Whether the app is debuggable or not. Specify `false` if you want good performance in debug builds - enable_debuggable = localProperties['debuggable'] ?: true - // Ending part of package name. - // Provide, for example, `application_id_suffix=.debug` in local.properties - // to allow debug & release versions to coexist - application_id_suffix = localProperties['application_id_suffix'] ?: '' - - // Compression level for debug AND release apk. 0 = disable compression. Max is 9 - compression_level = localProperties['compression_level'] ?: '0' - - // NOTE: If you need a different version of something, provide it in `local.properties` - // like so: compose_version=123, or gradle_plugin_version=1.2.3, etc - } - repositories { - google() - mavenCentral() - } - dependencies { - classpath "com.android.tools.build:gradle:$gradle_plugin_version" - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath "org.jetbrains.kotlin:kotlin-serialization:1.3.2" - - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - } -}// Top-level build file where you can add configuration options common to all sub-projects/modules. -plugins { - id 'com.android.application' version "$gradle_plugin_version" apply false - id 'com.android.library' version "$gradle_plugin_version" apply false - id 'org.jetbrains.kotlin.android' version "$kotlin_version" apply false - id 'org.jetbrains.kotlin.plugin.serialization' version "$kotlin_version" -} - -task clean(type: Delete) { - delete rootProject.buildDir -} \ No newline at end of file diff --git a/apps/multiplatform/build.gradle.kts b/apps/multiplatform/build.gradle.kts new file mode 100644 index 000000000..94cecd172 --- /dev/null +++ b/apps/multiplatform/build.gradle.kts @@ -0,0 +1,73 @@ +import org.gradle.initialization.Environment.Properties +import java.io.File +import java.io.FileInputStream + +buildscript { + val prop = java.util.Properties().apply { + try { + load(java.io.FileInputStream(File(rootProject.rootDir, "local.properties"))) + } catch (e: Exception) { + // No file was created + } + } + extra.set("compose.version", prop["compose.version"] ?: extra["compose.version"]) + extra.set("kotlin.version", prop["kotlin.version"] ?: extra["kotlin.version"]) + extra.set("gradle.plugin.version", prop["gradle.plugin.version"] ?: extra["gradle.plugin.version"]) + extra.set("abi_filter", prop["abi_filter"] ?: "arm64-v8a") + // Name that will be shown for debug build. By default, it is from strings + extra.set("app.name", prop["app.name"] ?: "@string/app_name") + // Whether the app is debuggable or not. Specify `false` if yo`u want good performance in debug builds + extra.set("enable_debuggable", prop["debuggable"] != "false") + // Ending part of package name. + // Provide, for example, `application_id.suffix=.debug` in local.properties + // to allow debug & release versions to coexist + extra.set("application_id.suffix", prop["application_id.suffix"] ?: "") + // Compression level for debug AND release apk. 0 = disable compression. Max is 9 + extra.set("compression.level", (prop["compression.level"] as String?)?.toIntOrNull() ?: 0) + // NOTE: If you need a different version of something, provide it in `local.properties` + // like so: compose.version=123, or gradle.plugin.version=1.2.3, etc + repositories { + google() + mavenCentral() + } + dependencies { + classpath("com.android.tools.build:gradle:${rootProject.extra["gradle.plugin.version"]}") + classpath(kotlin("gradle-plugin", version = rootProject.extra["kotlin.version"] as String)) + classpath("org.jetbrains.kotlin:kotlin-serialization:1.3.2") + classpath("dev.icerock.moko:resources-generator:0.22.3") + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +}// Top-level build file where you can add configuration options common to all sub-projects/modules. +/*plugins { + id "com.android.application" version "$gradle_plugin_version" apply false + id "com.android.library" version "$gradle_plugin_version" apply false + id "org.jetbrains.kotlin.android" version "$kotlin_version" apply false + id "org.jetbrains.kotlin.plugin.serialization" version "$kotlin_version" +}*/ + +group = "chat.simplex" +version = extra["android.version_name"] as String + +allprojects { + repositories { + google() + mavenCentral() + maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") + maven("https://jitpack.io") + } +} + +plugins { + kotlin("multiplatform") apply false + kotlin("android") apply false + id("com.android.application") apply false + id("com.android.library") apply false + id("org.jetbrains.compose") apply false + id("org.jetbrains.kotlin.plugin.serialization") apply false +} + +tasks.register("clean", Delete::class) { + delete(rootProject.buildDir) +} diff --git a/apps/multiplatform/common/build.gradle.kts b/apps/multiplatform/common/build.gradle.kts new file mode 100644 index 000000000..c3474f451 --- /dev/null +++ b/apps/multiplatform/common/build.gradle.kts @@ -0,0 +1,140 @@ +plugins { + kotlin("multiplatform") + id("org.jetbrains.compose") + id("com.android.library") + id("org.jetbrains.kotlin.plugin.serialization") + id("dev.icerock.mobile.multiplatform-resources") + id("com.github.gmazzo.buildconfig") version "4.0.4" +} + +group = "chat.simplex" +version = extra["android.version_name"] as String + +kotlin { + android() + jvm("desktop") { + jvmToolchain(11) + } + sourceSets { + all { + languageSettings { + optIn("kotlinx.coroutines.DelicateCoroutinesApi") + optIn("androidx.compose.foundation.ExperimentalFoundationApi") + optIn("androidx.compose.ui.text.ExperimentalTextApi") + optIn("androidx.compose.material.ExperimentalMaterialApi") + optIn("com.arkivanov.decompose.ExperimentalDecomposeApi") + optIn("kotlinx.serialization.InternalSerializationApi") + optIn("kotlinx.serialization.ExperimentalSerializationApi") + optIn("androidx.compose.ui.ExperimentalComposeUiApi") + optIn("com.google.accompanist.permissions.ExperimentalPermissionsApi") + } + } + + val commonMain by getting { + kotlin.srcDir("./build/generated/moko/commonMain/src/") + dependencies { + api(compose.runtime) + api(compose.foundation) + api(compose.material) + api("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2") + api("org.jetbrains.kotlinx:kotlinx-datetime:0.3.2") + api("com.russhwolf:multiplatform-settings:1.0.0") + api("com.charleskorn.kaml:kaml:0.43.0") + api("dev.icerock.moko:resources-compose:0.22.3") + api("org.jetbrains.compose.ui:ui-text:${rootProject.extra["compose.version"] as String}") + implementation("org.jetbrains.compose.components:components-animatedimage:${rootProject.extra["compose.version"] as String}") + //Barcode + api("org.boofcv:boofcv-core:0.40.1") + implementation("com.godaddy.android.colorpicker:compose-color-picker-jvm:0.7.0") + // Link Previews + implementation("org.jsoup:jsoup:1.13.1") + } + } + val commonTest by getting { + dependencies { + implementation(kotlin("test")) + } + } + // LALAL CHANGE TO IMPLEMENTATION + val androidMain by getting { + dependencies { + api("androidx.appcompat:appcompat:1.5.1") + api("androidx.core:core-ktx:1.9.0") + api("androidx.activity:activity-compose:1.5.0") + val work_version = "2.7.1" + api("androidx.work:work-runtime-ktx:$work_version") + api("androidx.work:work-multiprocess:$work_version") + api("com.google.accompanist:accompanist-insets:0.23.0") + api("dev.icerock.moko:resources:0.22.3") + + // Video support + api("com.google.android.exoplayer:exoplayer:2.17.1") + + // Biometric authentication + api("androidx.biometric:biometric:1.2.0-alpha04") + + //Barcode + api("org.boofcv:boofcv-android:0.40.1") + + //Camera Permission + api("com.google.accompanist:accompanist-permissions:0.23.0") + + api("androidx.webkit:webkit:1.4.0") + + // GIFs support + api("io.coil-kt:coil-compose:2.1.0") + api("io.coil-kt:coil-gif:2.1.0") + + api("com.jakewharton:process-phoenix:2.1.2") + + val camerax_version = "1.1.0-beta01" + api("androidx.camera:camera-core:${camerax_version}") + api("androidx.camera:camera-camera2:${camerax_version}") + api("androidx.camera:camera-lifecycle:${camerax_version}") + api("androidx.camera:camera-view:${camerax_version}") + + // LALAL REPLACE IT WITH SOURCE + // Wheel picker + api("com.github.zj565061763:compose-wheel-picker:1.0.0-alpha10") + + // LALAL REMOVE + api("org.jsoup:jsoup:1.13.1") + api("com.godaddy.android.colorpicker:compose-color-picker-jvm:0.7.0") + api("androidx.compose.ui:ui-tooling-preview:${extra["compose.version"]}") + } + } + val desktopMain by getting { + dependencies { + implementation("dev.icerock.moko:resources:0.22.3") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-swing:1.7.1") + } + } + val desktopTest by getting + } +} + +android { + compileSdkVersion(33) + sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") + defaultConfig { + minSdkVersion(26) + targetSdkVersion(33) + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } +} + +multiplatformResources { + multiplatformResourcesPackage = "com.icerockdev.library" + // multiplatformResourcesClassName = "MR" +} + +buildConfig { + forClass("BuildConfigCommon") { + buildConfigField("String", "ANDROID_VERSION_NAME", "\"${extra["android.version_name"]}\"") + buildConfigField("int", "ANDROID_VERSION_CODE", "${extra["android.version_code"]}") + buildConfigField("String", "DESKTOP_VERSION_NAME", "\"${extra["desktop.version_name"]}\"") + } +} diff --git a/apps/multiplatform/common/src/androidMain/AndroidManifest.xml b/apps/multiplatform/common/src/androidMain/AndroidManifest.xml new file mode 100644 index 000000000..74520465a --- /dev/null +++ b/apps/multiplatform/common/src/androidMain/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + + diff --git a/apps/multiplatform/android/src/main/cpp/CMakeLists.txt b/apps/multiplatform/common/src/commonMain/cpp/android/CMakeLists.txt similarity index 99% rename from apps/multiplatform/android/src/main/cpp/CMakeLists.txt rename to apps/multiplatform/common/src/commonMain/cpp/android/CMakeLists.txt index de688975c..44cb31d42 100644 --- a/apps/multiplatform/android/src/main/cpp/CMakeLists.txt +++ b/apps/multiplatform/common/src/commonMain/cpp/android/CMakeLists.txt @@ -64,4 +64,4 @@ target_link_libraries( # Specifies the target library. # Links the target library to the log library # included in the NDK. - ${log-lib}) \ No newline at end of file + ${log-lib}) diff --git a/apps/multiplatform/android/src/main/cpp/simplex-api.c b/apps/multiplatform/common/src/commonMain/cpp/android/simplex-api.c similarity index 100% rename from apps/multiplatform/android/src/main/cpp/simplex-api.c rename to apps/multiplatform/common/src/commonMain/cpp/android/simplex-api.c diff --git a/apps/multiplatform/common/src/commonMain/cpp/desktop/CMakeLists.txt b/apps/multiplatform/common/src/commonMain/cpp/desktop/CMakeLists.txt new file mode 100644 index 000000000..2f8f119d7 --- /dev/null +++ b/apps/multiplatform/common/src/commonMain/cpp/desktop/CMakeLists.txt @@ -0,0 +1,92 @@ +# Manually downloaded headers because `find_package(JNI REQUIRED)` doesn't work while cross-compiling: + +# https://raw.githubusercontent.com/openjdk/jdk/master/src/java.base/share/native/include/jni.h +include_directories(${CMAKE_SOURCE_DIR}/include) +if(UNIX) + # https://raw.githubusercontent.com/openjdk/jdk/master/src/java.base/unix/native/include/jni_md.h + include_directories(${CMAKE_SOURCE_DIR}/include/unix) +elseif(WIN32) + # https://raw.githubusercontent.com/openjdk/jdk/master/src/java.base/windows/native/include/jni_md.h + include_directories(${CMAKE_SOURCE_DIR}/include/windows) +endif() + +# Sets the minimum version of CMake required to build the native library. +cmake_minimum_required(VERSION 3.10.2) + +# Declares and names the project. +project("app") + +if(UNIX AND NOT APPLE) + set(OS_LIB_PATH "linux") + set(OS_LIB_EXT "so") +elseif(WIN32) + set(OS_LIB_PATH "windows") + set(OS_LIB_EXT "dll") +else() + set(OS_LIB_PATH "mac") + set(OS_LIB_EXT "dylib") + set(CMAKE_MACOSX_RPATH 1) + set(CMAKE_BUILD_RPATH "@loader_path") +endif() + +if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "amd64") + set(OS_LIB_ARCH "x86_64") +elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm64") + set(OS_LIB_ARCH "aarch64") +else() + set(OS_LIB_ARCH "${CMAKE_SYSTEM_PROCESSOR}") +endif() + +# Makes ld search libs in the same dir as libapp-lib, not in system dirs +#set(CMAKE_BUILD_RPATH "$ORIGIN") + +# Creates and names a library, sets it as either STATIC +# or SHARED, and provides the relative paths to its source code. +# You can define multiple libraries, and CMake builds them for you. +# Gradle automatically packages shared libraries with your APK. + +add_library( # Sets the name of the library. + app-lib + + # Sets the library as a shared library. + SHARED + + # Provides a relative path to your source file(s). + simplex-api.c) + +add_library( simplex SHARED IMPORTED ) +# Lib has different name because of version, find it +FILE(GLOB SIMPLEXLIB ${CMAKE_SOURCE_DIR}/libs/${OS_LIB_PATH}-${OS_LIB_ARCH}/libHSsimplex-chat-*.${OS_LIB_EXT}) +set_target_properties( simplex PROPERTIES IMPORTED_LOCATION ${SIMPLEXLIB}) + + +# Specifies libraries CMake should link to your target library. You +# can link multiple libraries, such as libraries you define in this +# build script, prebuilt third-party libraries, or system libraries. +if(NOT APPLE) + target_link_libraries(app-lib simplex) +else() + # Without direct linking it can't find hs_init in linking step + add_library( rts SHARED IMPORTED ) + FILE(GLOB RTSLIB ${CMAKE_SOURCE_DIR}/libs/${OS_LIB_PATH}-${OS_LIB_ARCH}/deps/libHSrts_thr-*.${OS_LIB_EXT}) + set_target_properties( rts PROPERTIES IMPORTED_LOCATION ${RTSLIB}) + + target_link_libraries(app-lib rts simplex) +endif() + + + +# Trying to copy resulting files into needed directory, but none of these work for some reason. This could allow to +# remove gradle's copy hooks +#add_custom_target(lalal) +#MACRO(POST_BUILD_COPY src_files dest_path) +# ADD_CUSTOM_COMMAND(TARGET lalal POST_BUILD +# COMMAND ${CMAKE_COMMAND} -E copy ${src_files} ${dest_path}) +#ENDMACRO(POST_BUILD_COPY src_files dest_path) + +#file(COPY "${CMAKE_SOURCE_DIR}/libs/${OS_LIB_PATH}-${OS_LIB_ARCH}/libsimplex.${OS_LIB_EXT}" DESTINATION "../../resources/libs/${OS_LIB_PATH}-${OS_LIB_ARCH}/libsimplex.${OS_LIB_EXT}") +#POST_BUILD_COPY("${CMAKE_BINARY_DIR}/libapp-lib.${OS_LIB_EXT}" "../resources/libs/${OS_LIB_PATH}-${OS_LIB_ARCH}/") + +#add_custom_command(TARGET lalal POST_BUILD +# COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/libapp-lib.${OS_LIB_EXT} "../../resources/libs/${OS_LIB_PATH}-${OS_LIB_ARCH}/libapp-lib.${OS_LIB_EXT}" +#) diff --git a/apps/multiplatform/common/src/commonMain/cpp/desktop/include/jni.h b/apps/multiplatform/common/src/commonMain/cpp/desktop/include/jni.h new file mode 100644 index 000000000..c85da1bc6 --- /dev/null +++ b/apps/multiplatform/common/src/commonMain/cpp/desktop/include/jni.h @@ -0,0 +1,2001 @@ +/* + * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * We used part of Netscape's Java Runtime Interface (JRI) as the starting + * point of our design and implementation. + */ + +/****************************************************************************** + * Java Runtime Interface + * Copyright (c) 1996 Netscape Communications Corporation. All rights reserved. + *****************************************************************************/ + +#ifndef _JAVASOFT_JNI_H_ +#define _JAVASOFT_JNI_H_ + +#include +#include + +/* jni_md.h contains the machine-dependent typedefs for jbyte, jint + and jlong */ + +#include "jni_md.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * JNI Types + */ + +#ifndef JNI_TYPES_ALREADY_DEFINED_IN_JNI_MD_H + +typedef unsigned char jboolean; +typedef unsigned short jchar; +typedef short jshort; +typedef float jfloat; +typedef double jdouble; + +typedef jint jsize; + +#ifdef __cplusplus + +class _jobject {}; +class _jclass : public _jobject {}; +class _jthrowable : public _jobject {}; +class _jstring : public _jobject {}; +class _jarray : public _jobject {}; +class _jbooleanArray : public _jarray {}; +class _jbyteArray : public _jarray {}; +class _jcharArray : public _jarray {}; +class _jshortArray : public _jarray {}; +class _jintArray : public _jarray {}; +class _jlongArray : public _jarray {}; +class _jfloatArray : public _jarray {}; +class _jdoubleArray : public _jarray {}; +class _jobjectArray : public _jarray {}; + +typedef _jobject *jobject; +typedef _jclass *jclass; +typedef _jthrowable *jthrowable; +typedef _jstring *jstring; +typedef _jarray *jarray; +typedef _jbooleanArray *jbooleanArray; +typedef _jbyteArray *jbyteArray; +typedef _jcharArray *jcharArray; +typedef _jshortArray *jshortArray; +typedef _jintArray *jintArray; +typedef _jlongArray *jlongArray; +typedef _jfloatArray *jfloatArray; +typedef _jdoubleArray *jdoubleArray; +typedef _jobjectArray *jobjectArray; + +#else + +struct _jobject; + +typedef struct _jobject *jobject; +typedef jobject jclass; +typedef jobject jthrowable; +typedef jobject jstring; +typedef jobject jarray; +typedef jarray jbooleanArray; +typedef jarray jbyteArray; +typedef jarray jcharArray; +typedef jarray jshortArray; +typedef jarray jintArray; +typedef jarray jlongArray; +typedef jarray jfloatArray; +typedef jarray jdoubleArray; +typedef jarray jobjectArray; + +#endif + +typedef jobject jweak; + +typedef union jvalue { + jboolean z; + jbyte b; + jchar c; + jshort s; + jint i; + jlong j; + jfloat f; + jdouble d; + jobject l; +} jvalue; + +struct _jfieldID; +typedef struct _jfieldID *jfieldID; + +struct _jmethodID; +typedef struct _jmethodID *jmethodID; + +/* Return values from jobjectRefType */ +typedef enum _jobjectType { + JNIInvalidRefType = 0, + JNILocalRefType = 1, + JNIGlobalRefType = 2, + JNIWeakGlobalRefType = 3 +} jobjectRefType; + + +#endif /* JNI_TYPES_ALREADY_DEFINED_IN_JNI_MD_H */ + +/* + * jboolean constants + */ + +#define JNI_FALSE 0 +#define JNI_TRUE 1 + +/* + * possible return values for JNI functions. + */ + +#define JNI_OK 0 /* success */ +#define JNI_ERR (-1) /* unknown error */ +#define JNI_EDETACHED (-2) /* thread detached from the VM */ +#define JNI_EVERSION (-3) /* JNI version error */ +#define JNI_ENOMEM (-4) /* not enough memory */ +#define JNI_EEXIST (-5) /* VM already created */ +#define JNI_EINVAL (-6) /* invalid arguments */ + +/* + * used in ReleaseScalarArrayElements + */ + +#define JNI_COMMIT 1 +#define JNI_ABORT 2 + +/* + * used in RegisterNatives to describe native method name, signature, + * and function pointer. + */ + +typedef struct { + char *name; + char *signature; + void *fnPtr; +} JNINativeMethod; + +/* + * JNI Native Method Interface. + */ + +struct JNINativeInterface_; + +struct JNIEnv_; + +#ifdef __cplusplus +typedef JNIEnv_ JNIEnv; +#else +typedef const struct JNINativeInterface_ *JNIEnv; +#endif + +/* + * JNI Invocation Interface. + */ + +struct JNIInvokeInterface_; + +struct JavaVM_; + +#ifdef __cplusplus +typedef JavaVM_ JavaVM; +#else +typedef const struct JNIInvokeInterface_ *JavaVM; +#endif + +struct JNINativeInterface_ { + void *reserved0; + void *reserved1; + void *reserved2; + + void *reserved3; + jint (JNICALL *GetVersion)(JNIEnv *env); + + jclass (JNICALL *DefineClass) + (JNIEnv *env, const char *name, jobject loader, const jbyte *buf, + jsize len); + jclass (JNICALL *FindClass) + (JNIEnv *env, const char *name); + + jmethodID (JNICALL *FromReflectedMethod) + (JNIEnv *env, jobject method); + jfieldID (JNICALL *FromReflectedField) + (JNIEnv *env, jobject field); + + jobject (JNICALL *ToReflectedMethod) + (JNIEnv *env, jclass cls, jmethodID methodID, jboolean isStatic); + + jclass (JNICALL *GetSuperclass) + (JNIEnv *env, jclass sub); + jboolean (JNICALL *IsAssignableFrom) + (JNIEnv *env, jclass sub, jclass sup); + + jobject (JNICALL *ToReflectedField) + (JNIEnv *env, jclass cls, jfieldID fieldID, jboolean isStatic); + + jint (JNICALL *Throw) + (JNIEnv *env, jthrowable obj); + jint (JNICALL *ThrowNew) + (JNIEnv *env, jclass clazz, const char *msg); + jthrowable (JNICALL *ExceptionOccurred) + (JNIEnv *env); + void (JNICALL *ExceptionDescribe) + (JNIEnv *env); + void (JNICALL *ExceptionClear) + (JNIEnv *env); + void (JNICALL *FatalError) + (JNIEnv *env, const char *msg); + + jint (JNICALL *PushLocalFrame) + (JNIEnv *env, jint capacity); + jobject (JNICALL *PopLocalFrame) + (JNIEnv *env, jobject result); + + jobject (JNICALL *NewGlobalRef) + (JNIEnv *env, jobject lobj); + void (JNICALL *DeleteGlobalRef) + (JNIEnv *env, jobject gref); + void (JNICALL *DeleteLocalRef) + (JNIEnv *env, jobject obj); + jboolean (JNICALL *IsSameObject) + (JNIEnv *env, jobject obj1, jobject obj2); + jobject (JNICALL *NewLocalRef) + (JNIEnv *env, jobject ref); + jint (JNICALL *EnsureLocalCapacity) + (JNIEnv *env, jint capacity); + + jobject (JNICALL *AllocObject) + (JNIEnv *env, jclass clazz); + jobject (JNICALL *NewObject) + (JNIEnv *env, jclass clazz, jmethodID methodID, ...); + jobject (JNICALL *NewObjectV) + (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); + jobject (JNICALL *NewObjectA) + (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); + + jclass (JNICALL *GetObjectClass) + (JNIEnv *env, jobject obj); + jboolean (JNICALL *IsInstanceOf) + (JNIEnv *env, jobject obj, jclass clazz); + + jmethodID (JNICALL *GetMethodID) + (JNIEnv *env, jclass clazz, const char *name, const char *sig); + + jobject (JNICALL *CallObjectMethod) + (JNIEnv *env, jobject obj, jmethodID methodID, ...); + jobject (JNICALL *CallObjectMethodV) + (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); + jobject (JNICALL *CallObjectMethodA) + (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args); + + jboolean (JNICALL *CallBooleanMethod) + (JNIEnv *env, jobject obj, jmethodID methodID, ...); + jboolean (JNICALL *CallBooleanMethodV) + (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); + jboolean (JNICALL *CallBooleanMethodA) + (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args); + + jbyte (JNICALL *CallByteMethod) + (JNIEnv *env, jobject obj, jmethodID methodID, ...); + jbyte (JNICALL *CallByteMethodV) + (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); + jbyte (JNICALL *CallByteMethodA) + (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args); + + jchar (JNICALL *CallCharMethod) + (JNIEnv *env, jobject obj, jmethodID methodID, ...); + jchar (JNICALL *CallCharMethodV) + (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); + jchar (JNICALL *CallCharMethodA) + (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args); + + jshort (JNICALL *CallShortMethod) + (JNIEnv *env, jobject obj, jmethodID methodID, ...); + jshort (JNICALL *CallShortMethodV) + (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); + jshort (JNICALL *CallShortMethodA) + (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args); + + jint (JNICALL *CallIntMethod) + (JNIEnv *env, jobject obj, jmethodID methodID, ...); + jint (JNICALL *CallIntMethodV) + (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); + jint (JNICALL *CallIntMethodA) + (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args); + + jlong (JNICALL *CallLongMethod) + (JNIEnv *env, jobject obj, jmethodID methodID, ...); + jlong (JNICALL *CallLongMethodV) + (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); + jlong (JNICALL *CallLongMethodA) + (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args); + + jfloat (JNICALL *CallFloatMethod) + (JNIEnv *env, jobject obj, jmethodID methodID, ...); + jfloat (JNICALL *CallFloatMethodV) + (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); + jfloat (JNICALL *CallFloatMethodA) + (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args); + + jdouble (JNICALL *CallDoubleMethod) + (JNIEnv *env, jobject obj, jmethodID methodID, ...); + jdouble (JNICALL *CallDoubleMethodV) + (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); + jdouble (JNICALL *CallDoubleMethodA) + (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args); + + void (JNICALL *CallVoidMethod) + (JNIEnv *env, jobject obj, jmethodID methodID, ...); + void (JNICALL *CallVoidMethodV) + (JNIEnv *env, jobject obj, jmethodID methodID, va_list args); + void (JNICALL *CallVoidMethodA) + (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args); + + jobject (JNICALL *CallNonvirtualObjectMethod) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); + jobject (JNICALL *CallNonvirtualObjectMethodV) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + va_list args); + jobject (JNICALL *CallNonvirtualObjectMethodA) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + const jvalue * args); + + jboolean (JNICALL *CallNonvirtualBooleanMethod) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); + jboolean (JNICALL *CallNonvirtualBooleanMethodV) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + va_list args); + jboolean (JNICALL *CallNonvirtualBooleanMethodA) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + const jvalue * args); + + jbyte (JNICALL *CallNonvirtualByteMethod) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); + jbyte (JNICALL *CallNonvirtualByteMethodV) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + va_list args); + jbyte (JNICALL *CallNonvirtualByteMethodA) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + const jvalue *args); + + jchar (JNICALL *CallNonvirtualCharMethod) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); + jchar (JNICALL *CallNonvirtualCharMethodV) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + va_list args); + jchar (JNICALL *CallNonvirtualCharMethodA) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + const jvalue *args); + + jshort (JNICALL *CallNonvirtualShortMethod) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); + jshort (JNICALL *CallNonvirtualShortMethodV) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + va_list args); + jshort (JNICALL *CallNonvirtualShortMethodA) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + const jvalue *args); + + jint (JNICALL *CallNonvirtualIntMethod) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); + jint (JNICALL *CallNonvirtualIntMethodV) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + va_list args); + jint (JNICALL *CallNonvirtualIntMethodA) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + const jvalue *args); + + jlong (JNICALL *CallNonvirtualLongMethod) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); + jlong (JNICALL *CallNonvirtualLongMethodV) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + va_list args); + jlong (JNICALL *CallNonvirtualLongMethodA) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + const jvalue *args); + + jfloat (JNICALL *CallNonvirtualFloatMethod) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); + jfloat (JNICALL *CallNonvirtualFloatMethodV) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + va_list args); + jfloat (JNICALL *CallNonvirtualFloatMethodA) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + const jvalue *args); + + jdouble (JNICALL *CallNonvirtualDoubleMethod) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); + jdouble (JNICALL *CallNonvirtualDoubleMethodV) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + va_list args); + jdouble (JNICALL *CallNonvirtualDoubleMethodA) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + const jvalue *args); + + void (JNICALL *CallNonvirtualVoidMethod) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...); + void (JNICALL *CallNonvirtualVoidMethodV) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + va_list args); + void (JNICALL *CallNonvirtualVoidMethodA) + (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, + const jvalue * args); + + jfieldID (JNICALL *GetFieldID) + (JNIEnv *env, jclass clazz, const char *name, const char *sig); + + jobject (JNICALL *GetObjectField) + (JNIEnv *env, jobject obj, jfieldID fieldID); + jboolean (JNICALL *GetBooleanField) + (JNIEnv *env, jobject obj, jfieldID fieldID); + jbyte (JNICALL *GetByteField) + (JNIEnv *env, jobject obj, jfieldID fieldID); + jchar (JNICALL *GetCharField) + (JNIEnv *env, jobject obj, jfieldID fieldID); + jshort (JNICALL *GetShortField) + (JNIEnv *env, jobject obj, jfieldID fieldID); + jint (JNICALL *GetIntField) + (JNIEnv *env, jobject obj, jfieldID fieldID); + jlong (JNICALL *GetLongField) + (JNIEnv *env, jobject obj, jfieldID fieldID); + jfloat (JNICALL *GetFloatField) + (JNIEnv *env, jobject obj, jfieldID fieldID); + jdouble (JNICALL *GetDoubleField) + (JNIEnv *env, jobject obj, jfieldID fieldID); + + void (JNICALL *SetObjectField) + (JNIEnv *env, jobject obj, jfieldID fieldID, jobject val); + void (JNICALL *SetBooleanField) + (JNIEnv *env, jobject obj, jfieldID fieldID, jboolean val); + void (JNICALL *SetByteField) + (JNIEnv *env, jobject obj, jfieldID fieldID, jbyte val); + void (JNICALL *SetCharField) + (JNIEnv *env, jobject obj, jfieldID fieldID, jchar val); + void (JNICALL *SetShortField) + (JNIEnv *env, jobject obj, jfieldID fieldID, jshort val); + void (JNICALL *SetIntField) + (JNIEnv *env, jobject obj, jfieldID fieldID, jint val); + void (JNICALL *SetLongField) + (JNIEnv *env, jobject obj, jfieldID fieldID, jlong val); + void (JNICALL *SetFloatField) + (JNIEnv *env, jobject obj, jfieldID fieldID, jfloat val); + void (JNICALL *SetDoubleField) + (JNIEnv *env, jobject obj, jfieldID fieldID, jdouble val); + + jmethodID (JNICALL *GetStaticMethodID) + (JNIEnv *env, jclass clazz, const char *name, const char *sig); + + jobject (JNICALL *CallStaticObjectMethod) + (JNIEnv *env, jclass clazz, jmethodID methodID, ...); + jobject (JNICALL *CallStaticObjectMethodV) + (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); + jobject (JNICALL *CallStaticObjectMethodA) + (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); + + jboolean (JNICALL *CallStaticBooleanMethod) + (JNIEnv *env, jclass clazz, jmethodID methodID, ...); + jboolean (JNICALL *CallStaticBooleanMethodV) + (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); + jboolean (JNICALL *CallStaticBooleanMethodA) + (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); + + jbyte (JNICALL *CallStaticByteMethod) + (JNIEnv *env, jclass clazz, jmethodID methodID, ...); + jbyte (JNICALL *CallStaticByteMethodV) + (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); + jbyte (JNICALL *CallStaticByteMethodA) + (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); + + jchar (JNICALL *CallStaticCharMethod) + (JNIEnv *env, jclass clazz, jmethodID methodID, ...); + jchar (JNICALL *CallStaticCharMethodV) + (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); + jchar (JNICALL *CallStaticCharMethodA) + (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); + + jshort (JNICALL *CallStaticShortMethod) + (JNIEnv *env, jclass clazz, jmethodID methodID, ...); + jshort (JNICALL *CallStaticShortMethodV) + (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); + jshort (JNICALL *CallStaticShortMethodA) + (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); + + jint (JNICALL *CallStaticIntMethod) + (JNIEnv *env, jclass clazz, jmethodID methodID, ...); + jint (JNICALL *CallStaticIntMethodV) + (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); + jint (JNICALL *CallStaticIntMethodA) + (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); + + jlong (JNICALL *CallStaticLongMethod) + (JNIEnv *env, jclass clazz, jmethodID methodID, ...); + jlong (JNICALL *CallStaticLongMethodV) + (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); + jlong (JNICALL *CallStaticLongMethodA) + (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); + + jfloat (JNICALL *CallStaticFloatMethod) + (JNIEnv *env, jclass clazz, jmethodID methodID, ...); + jfloat (JNICALL *CallStaticFloatMethodV) + (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); + jfloat (JNICALL *CallStaticFloatMethodA) + (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); + + jdouble (JNICALL *CallStaticDoubleMethod) + (JNIEnv *env, jclass clazz, jmethodID methodID, ...); + jdouble (JNICALL *CallStaticDoubleMethodV) + (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); + jdouble (JNICALL *CallStaticDoubleMethodA) + (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); + + void (JNICALL *CallStaticVoidMethod) + (JNIEnv *env, jclass cls, jmethodID methodID, ...); + void (JNICALL *CallStaticVoidMethodV) + (JNIEnv *env, jclass cls, jmethodID methodID, va_list args); + void (JNICALL *CallStaticVoidMethodA) + (JNIEnv *env, jclass cls, jmethodID methodID, const jvalue * args); + + jfieldID (JNICALL *GetStaticFieldID) + (JNIEnv *env, jclass clazz, const char *name, const char *sig); + jobject (JNICALL *GetStaticObjectField) + (JNIEnv *env, jclass clazz, jfieldID fieldID); + jboolean (JNICALL *GetStaticBooleanField) + (JNIEnv *env, jclass clazz, jfieldID fieldID); + jbyte (JNICALL *GetStaticByteField) + (JNIEnv *env, jclass clazz, jfieldID fieldID); + jchar (JNICALL *GetStaticCharField) + (JNIEnv *env, jclass clazz, jfieldID fieldID); + jshort (JNICALL *GetStaticShortField) + (JNIEnv *env, jclass clazz, jfieldID fieldID); + jint (JNICALL *GetStaticIntField) + (JNIEnv *env, jclass clazz, jfieldID fieldID); + jlong (JNICALL *GetStaticLongField) + (JNIEnv *env, jclass clazz, jfieldID fieldID); + jfloat (JNICALL *GetStaticFloatField) + (JNIEnv *env, jclass clazz, jfieldID fieldID); + jdouble (JNICALL *GetStaticDoubleField) + (JNIEnv *env, jclass clazz, jfieldID fieldID); + + void (JNICALL *SetStaticObjectField) + (JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value); + void (JNICALL *SetStaticBooleanField) + (JNIEnv *env, jclass clazz, jfieldID fieldID, jboolean value); + void (JNICALL *SetStaticByteField) + (JNIEnv *env, jclass clazz, jfieldID fieldID, jbyte value); + void (JNICALL *SetStaticCharField) + (JNIEnv *env, jclass clazz, jfieldID fieldID, jchar value); + void (JNICALL *SetStaticShortField) + (JNIEnv *env, jclass clazz, jfieldID fieldID, jshort value); + void (JNICALL *SetStaticIntField) + (JNIEnv *env, jclass clazz, jfieldID fieldID, jint value); + void (JNICALL *SetStaticLongField) + (JNIEnv *env, jclass clazz, jfieldID fieldID, jlong value); + void (JNICALL *SetStaticFloatField) + (JNIEnv *env, jclass clazz, jfieldID fieldID, jfloat value); + void (JNICALL *SetStaticDoubleField) + (JNIEnv *env, jclass clazz, jfieldID fieldID, jdouble value); + + jstring (JNICALL *NewString) + (JNIEnv *env, const jchar *unicode, jsize len); + jsize (JNICALL *GetStringLength) + (JNIEnv *env, jstring str); + const jchar *(JNICALL *GetStringChars) + (JNIEnv *env, jstring str, jboolean *isCopy); + void (JNICALL *ReleaseStringChars) + (JNIEnv *env, jstring str, const jchar *chars); + + jstring (JNICALL *NewStringUTF) + (JNIEnv *env, const char *utf); + jsize (JNICALL *GetStringUTFLength) + (JNIEnv *env, jstring str); + const char* (JNICALL *GetStringUTFChars) + (JNIEnv *env, jstring str, jboolean *isCopy); + void (JNICALL *ReleaseStringUTFChars) + (JNIEnv *env, jstring str, const char* chars); + + + jsize (JNICALL *GetArrayLength) + (JNIEnv *env, jarray array); + + jobjectArray (JNICALL *NewObjectArray) + (JNIEnv *env, jsize len, jclass clazz, jobject init); + jobject (JNICALL *GetObjectArrayElement) + (JNIEnv *env, jobjectArray array, jsize index); + void (JNICALL *SetObjectArrayElement) + (JNIEnv *env, jobjectArray array, jsize index, jobject val); + + jbooleanArray (JNICALL *NewBooleanArray) + (JNIEnv *env, jsize len); + jbyteArray (JNICALL *NewByteArray) + (JNIEnv *env, jsize len); + jcharArray (JNICALL *NewCharArray) + (JNIEnv *env, jsize len); + jshortArray (JNICALL *NewShortArray) + (JNIEnv *env, jsize len); + jintArray (JNICALL *NewIntArray) + (JNIEnv *env, jsize len); + jlongArray (JNICALL *NewLongArray) + (JNIEnv *env, jsize len); + jfloatArray (JNICALL *NewFloatArray) + (JNIEnv *env, jsize len); + jdoubleArray (JNICALL *NewDoubleArray) + (JNIEnv *env, jsize len); + + jboolean * (JNICALL *GetBooleanArrayElements) + (JNIEnv *env, jbooleanArray array, jboolean *isCopy); + jbyte * (JNICALL *GetByteArrayElements) + (JNIEnv *env, jbyteArray array, jboolean *isCopy); + jchar * (JNICALL *GetCharArrayElements) + (JNIEnv *env, jcharArray array, jboolean *isCopy); + jshort * (JNICALL *GetShortArrayElements) + (JNIEnv *env, jshortArray array, jboolean *isCopy); + jint * (JNICALL *GetIntArrayElements) + (JNIEnv *env, jintArray array, jboolean *isCopy); + jlong * (JNICALL *GetLongArrayElements) + (JNIEnv *env, jlongArray array, jboolean *isCopy); + jfloat * (JNICALL *GetFloatArrayElements) + (JNIEnv *env, jfloatArray array, jboolean *isCopy); + jdouble * (JNICALL *GetDoubleArrayElements) + (JNIEnv *env, jdoubleArray array, jboolean *isCopy); + + void (JNICALL *ReleaseBooleanArrayElements) + (JNIEnv *env, jbooleanArray array, jboolean *elems, jint mode); + void (JNICALL *ReleaseByteArrayElements) + (JNIEnv *env, jbyteArray array, jbyte *elems, jint mode); + void (JNICALL *ReleaseCharArrayElements) + (JNIEnv *env, jcharArray array, jchar *elems, jint mode); + void (JNICALL *ReleaseShortArrayElements) + (JNIEnv *env, jshortArray array, jshort *elems, jint mode); + void (JNICALL *ReleaseIntArrayElements) + (JNIEnv *env, jintArray array, jint *elems, jint mode); + void (JNICALL *ReleaseLongArrayElements) + (JNIEnv *env, jlongArray array, jlong *elems, jint mode); + void (JNICALL *ReleaseFloatArrayElements) + (JNIEnv *env, jfloatArray array, jfloat *elems, jint mode); + void (JNICALL *ReleaseDoubleArrayElements) + (JNIEnv *env, jdoubleArray array, jdouble *elems, jint mode); + + void (JNICALL *GetBooleanArrayRegion) + (JNIEnv *env, jbooleanArray array, jsize start, jsize l, jboolean *buf); + void (JNICALL *GetByteArrayRegion) + (JNIEnv *env, jbyteArray array, jsize start, jsize len, jbyte *buf); + void (JNICALL *GetCharArrayRegion) + (JNIEnv *env, jcharArray array, jsize start, jsize len, jchar *buf); + void (JNICALL *GetShortArrayRegion) + (JNIEnv *env, jshortArray array, jsize start, jsize len, jshort *buf); + void (JNICALL *GetIntArrayRegion) + (JNIEnv *env, jintArray array, jsize start, jsize len, jint *buf); + void (JNICALL *GetLongArrayRegion) + (JNIEnv *env, jlongArray array, jsize start, jsize len, jlong *buf); + void (JNICALL *GetFloatArrayRegion) + (JNIEnv *env, jfloatArray array, jsize start, jsize len, jfloat *buf); + void (JNICALL *GetDoubleArrayRegion) + (JNIEnv *env, jdoubleArray array, jsize start, jsize len, jdouble *buf); + + void (JNICALL *SetBooleanArrayRegion) + (JNIEnv *env, jbooleanArray array, jsize start, jsize l, const jboolean *buf); + void (JNICALL *SetByteArrayRegion) + (JNIEnv *env, jbyteArray array, jsize start, jsize len, const jbyte *buf); + void (JNICALL *SetCharArrayRegion) + (JNIEnv *env, jcharArray array, jsize start, jsize len, const jchar *buf); + void (JNICALL *SetShortArrayRegion) + (JNIEnv *env, jshortArray array, jsize start, jsize len, const jshort *buf); + void (JNICALL *SetIntArrayRegion) + (JNIEnv *env, jintArray array, jsize start, jsize len, const jint *buf); + void (JNICALL *SetLongArrayRegion) + (JNIEnv *env, jlongArray array, jsize start, jsize len, const jlong *buf); + void (JNICALL *SetFloatArrayRegion) + (JNIEnv *env, jfloatArray array, jsize start, jsize len, const jfloat *buf); + void (JNICALL *SetDoubleArrayRegion) + (JNIEnv *env, jdoubleArray array, jsize start, jsize len, const jdouble *buf); + + jint (JNICALL *RegisterNatives) + (JNIEnv *env, jclass clazz, const JNINativeMethod *methods, + jint nMethods); + jint (JNICALL *UnregisterNatives) + (JNIEnv *env, jclass clazz); + + jint (JNICALL *MonitorEnter) + (JNIEnv *env, jobject obj); + jint (JNICALL *MonitorExit) + (JNIEnv *env, jobject obj); + + jint (JNICALL *GetJavaVM) + (JNIEnv *env, JavaVM **vm); + + void (JNICALL *GetStringRegion) + (JNIEnv *env, jstring str, jsize start, jsize len, jchar *buf); + void (JNICALL *GetStringUTFRegion) + (JNIEnv *env, jstring str, jsize start, jsize len, char *buf); + + void * (JNICALL *GetPrimitiveArrayCritical) + (JNIEnv *env, jarray array, jboolean *isCopy); + void (JNICALL *ReleasePrimitiveArrayCritical) + (JNIEnv *env, jarray array, void *carray, jint mode); + + const jchar * (JNICALL *GetStringCritical) + (JNIEnv *env, jstring string, jboolean *isCopy); + void (JNICALL *ReleaseStringCritical) + (JNIEnv *env, jstring string, const jchar *cstring); + + jweak (JNICALL *NewWeakGlobalRef) + (JNIEnv *env, jobject obj); + void (JNICALL *DeleteWeakGlobalRef) + (JNIEnv *env, jweak ref); + + jboolean (JNICALL *ExceptionCheck) + (JNIEnv *env); + + jobject (JNICALL *NewDirectByteBuffer) + (JNIEnv* env, void* address, jlong capacity); + void* (JNICALL *GetDirectBufferAddress) + (JNIEnv* env, jobject buf); + jlong (JNICALL *GetDirectBufferCapacity) + (JNIEnv* env, jobject buf); + + /* New JNI 1.6 Features */ + + jobjectRefType (JNICALL *GetObjectRefType) + (JNIEnv* env, jobject obj); + + /* Module Features */ + + jobject (JNICALL *GetModule) + (JNIEnv* env, jclass clazz); + + /* Virtual threads */ + + jboolean (JNICALL *IsVirtualThread) + (JNIEnv* env, jobject obj); +}; + +/* + * We use inlined functions for C++ so that programmers can write: + * + * env->FindClass("java/lang/String") + * + * in C++ rather than: + * + * (*env)->FindClass(env, "java/lang/String") + * + * in C. + */ + +struct JNIEnv_ { + const struct JNINativeInterface_ *functions; +#ifdef __cplusplus + + jint GetVersion() { + return functions->GetVersion(this); + } + jclass DefineClass(const char *name, jobject loader, const jbyte *buf, + jsize len) { + return functions->DefineClass(this, name, loader, buf, len); + } + jclass FindClass(const char *name) { + return functions->FindClass(this, name); + } + jmethodID FromReflectedMethod(jobject method) { + return functions->FromReflectedMethod(this,method); + } + jfieldID FromReflectedField(jobject field) { + return functions->FromReflectedField(this,field); + } + + jobject ToReflectedMethod(jclass cls, jmethodID methodID, jboolean isStatic) { + return functions->ToReflectedMethod(this, cls, methodID, isStatic); + } + + jclass GetSuperclass(jclass sub) { + return functions->GetSuperclass(this, sub); + } + jboolean IsAssignableFrom(jclass sub, jclass sup) { + return functions->IsAssignableFrom(this, sub, sup); + } + + jobject ToReflectedField(jclass cls, jfieldID fieldID, jboolean isStatic) { + return functions->ToReflectedField(this,cls,fieldID,isStatic); + } + + jint Throw(jthrowable obj) { + return functions->Throw(this, obj); + } + jint ThrowNew(jclass clazz, const char *msg) { + return functions->ThrowNew(this, clazz, msg); + } + jthrowable ExceptionOccurred() { + return functions->ExceptionOccurred(this); + } + void ExceptionDescribe() { + functions->ExceptionDescribe(this); + } + void ExceptionClear() { + functions->ExceptionClear(this); + } + void FatalError(const char *msg) { + functions->FatalError(this, msg); + } + + jint PushLocalFrame(jint capacity) { + return functions->PushLocalFrame(this,capacity); + } + jobject PopLocalFrame(jobject result) { + return functions->PopLocalFrame(this,result); + } + + jobject NewGlobalRef(jobject lobj) { + return functions->NewGlobalRef(this,lobj); + } + void DeleteGlobalRef(jobject gref) { + functions->DeleteGlobalRef(this,gref); + } + void DeleteLocalRef(jobject obj) { + functions->DeleteLocalRef(this, obj); + } + + jboolean IsSameObject(jobject obj1, jobject obj2) { + return functions->IsSameObject(this,obj1,obj2); + } + + jobject NewLocalRef(jobject ref) { + return functions->NewLocalRef(this,ref); + } + jint EnsureLocalCapacity(jint capacity) { + return functions->EnsureLocalCapacity(this,capacity); + } + + jobject AllocObject(jclass clazz) { + return functions->AllocObject(this,clazz); + } + jobject NewObject(jclass clazz, jmethodID methodID, ...) { + va_list args; + jobject result; + va_start(args, methodID); + result = functions->NewObjectV(this,clazz,methodID,args); + va_end(args); + return result; + } + jobject NewObjectV(jclass clazz, jmethodID methodID, + va_list args) { + return functions->NewObjectV(this,clazz,methodID,args); + } + jobject NewObjectA(jclass clazz, jmethodID methodID, + const jvalue *args) { + return functions->NewObjectA(this,clazz,methodID,args); + } + + jclass GetObjectClass(jobject obj) { + return functions->GetObjectClass(this,obj); + } + jboolean IsInstanceOf(jobject obj, jclass clazz) { + return functions->IsInstanceOf(this,obj,clazz); + } + + jmethodID GetMethodID(jclass clazz, const char *name, + const char *sig) { + return functions->GetMethodID(this,clazz,name,sig); + } + + jobject CallObjectMethod(jobject obj, jmethodID methodID, ...) { + va_list args; + jobject result; + va_start(args,methodID); + result = functions->CallObjectMethodV(this,obj,methodID,args); + va_end(args); + return result; + } + jobject CallObjectMethodV(jobject obj, jmethodID methodID, + va_list args) { + return functions->CallObjectMethodV(this,obj,methodID,args); + } + jobject CallObjectMethodA(jobject obj, jmethodID methodID, + const jvalue * args) { + return functions->CallObjectMethodA(this,obj,methodID,args); + } + + jboolean CallBooleanMethod(jobject obj, + jmethodID methodID, ...) { + va_list args; + jboolean result; + va_start(args,methodID); + result = functions->CallBooleanMethodV(this,obj,methodID,args); + va_end(args); + return result; + } + jboolean CallBooleanMethodV(jobject obj, jmethodID methodID, + va_list args) { + return functions->CallBooleanMethodV(this,obj,methodID,args); + } + jboolean CallBooleanMethodA(jobject obj, jmethodID methodID, + const jvalue * args) { + return functions->CallBooleanMethodA(this,obj,methodID, args); + } + + jbyte CallByteMethod(jobject obj, jmethodID methodID, ...) { + va_list args; + jbyte result; + va_start(args,methodID); + result = functions->CallByteMethodV(this,obj,methodID,args); + va_end(args); + return result; + } + jbyte CallByteMethodV(jobject obj, jmethodID methodID, + va_list args) { + return functions->CallByteMethodV(this,obj,methodID,args); + } + jbyte CallByteMethodA(jobject obj, jmethodID methodID, + const jvalue * args) { + return functions->CallByteMethodA(this,obj,methodID,args); + } + + jchar CallCharMethod(jobject obj, jmethodID methodID, ...) { + va_list args; + jchar result; + va_start(args,methodID); + result = functions->CallCharMethodV(this,obj,methodID,args); + va_end(args); + return result; + } + jchar CallCharMethodV(jobject obj, jmethodID methodID, + va_list args) { + return functions->CallCharMethodV(this,obj,methodID,args); + } + jchar CallCharMethodA(jobject obj, jmethodID methodID, + const jvalue * args) { + return functions->CallCharMethodA(this,obj,methodID,args); + } + + jshort CallShortMethod(jobject obj, jmethodID methodID, ...) { + va_list args; + jshort result; + va_start(args,methodID); + result = functions->CallShortMethodV(this,obj,methodID,args); + va_end(args); + return result; + } + jshort CallShortMethodV(jobject obj, jmethodID methodID, + va_list args) { + return functions->CallShortMethodV(this,obj,methodID,args); + } + jshort CallShortMethodA(jobject obj, jmethodID methodID, + const jvalue * args) { + return functions->CallShortMethodA(this,obj,methodID,args); + } + + jint CallIntMethod(jobject obj, jmethodID methodID, ...) { + va_list args; + jint result; + va_start(args,methodID); + result = functions->CallIntMethodV(this,obj,methodID,args); + va_end(args); + return result; + } + jint CallIntMethodV(jobject obj, jmethodID methodID, + va_list args) { + return functions->CallIntMethodV(this,obj,methodID,args); + } + jint CallIntMethodA(jobject obj, jmethodID methodID, + const jvalue * args) { + return functions->CallIntMethodA(this,obj,methodID,args); + } + + jlong CallLongMethod(jobject obj, jmethodID methodID, ...) { + va_list args; + jlong result; + va_start(args,methodID); + result = functions->CallLongMethodV(this,obj,methodID,args); + va_end(args); + return result; + } + jlong CallLongMethodV(jobject obj, jmethodID methodID, + va_list args) { + return functions->CallLongMethodV(this,obj,methodID,args); + } + jlong CallLongMethodA(jobject obj, jmethodID methodID, + const jvalue * args) { + return functions->CallLongMethodA(this,obj,methodID,args); + } + + jfloat CallFloatMethod(jobject obj, jmethodID methodID, ...) { + va_list args; + jfloat result; + va_start(args,methodID); + result = functions->CallFloatMethodV(this,obj,methodID,args); + va_end(args); + return result; + } + jfloat CallFloatMethodV(jobject obj, jmethodID methodID, + va_list args) { + return functions->CallFloatMethodV(this,obj,methodID,args); + } + jfloat CallFloatMethodA(jobject obj, jmethodID methodID, + const jvalue * args) { + return functions->CallFloatMethodA(this,obj,methodID,args); + } + + jdouble CallDoubleMethod(jobject obj, jmethodID methodID, ...) { + va_list args; + jdouble result; + va_start(args,methodID); + result = functions->CallDoubleMethodV(this,obj,methodID,args); + va_end(args); + return result; + } + jdouble CallDoubleMethodV(jobject obj, jmethodID methodID, + va_list args) { + return functions->CallDoubleMethodV(this,obj,methodID,args); + } + jdouble CallDoubleMethodA(jobject obj, jmethodID methodID, + const jvalue * args) { + return functions->CallDoubleMethodA(this,obj,methodID,args); + } + + void CallVoidMethod(jobject obj, jmethodID methodID, ...) { + va_list args; + va_start(args,methodID); + functions->CallVoidMethodV(this,obj,methodID,args); + va_end(args); + } + void CallVoidMethodV(jobject obj, jmethodID methodID, + va_list args) { + functions->CallVoidMethodV(this,obj,methodID,args); + } + void CallVoidMethodA(jobject obj, jmethodID methodID, + const jvalue * args) { + functions->CallVoidMethodA(this,obj,methodID,args); + } + + jobject CallNonvirtualObjectMethod(jobject obj, jclass clazz, + jmethodID methodID, ...) { + va_list args; + jobject result; + va_start(args,methodID); + result = functions->CallNonvirtualObjectMethodV(this,obj,clazz, + methodID,args); + va_end(args); + return result; + } + jobject CallNonvirtualObjectMethodV(jobject obj, jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallNonvirtualObjectMethodV(this,obj,clazz, + methodID,args); + } + jobject CallNonvirtualObjectMethodA(jobject obj, jclass clazz, + jmethodID methodID, const jvalue * args) { + return functions->CallNonvirtualObjectMethodA(this,obj,clazz, + methodID,args); + } + + jboolean CallNonvirtualBooleanMethod(jobject obj, jclass clazz, + jmethodID methodID, ...) { + va_list args; + jboolean result; + va_start(args,methodID); + result = functions->CallNonvirtualBooleanMethodV(this,obj,clazz, + methodID,args); + va_end(args); + return result; + } + jboolean CallNonvirtualBooleanMethodV(jobject obj, jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallNonvirtualBooleanMethodV(this,obj,clazz, + methodID,args); + } + jboolean CallNonvirtualBooleanMethodA(jobject obj, jclass clazz, + jmethodID methodID, const jvalue * args) { + return functions->CallNonvirtualBooleanMethodA(this,obj,clazz, + methodID, args); + } + + jbyte CallNonvirtualByteMethod(jobject obj, jclass clazz, + jmethodID methodID, ...) { + va_list args; + jbyte result; + va_start(args,methodID); + result = functions->CallNonvirtualByteMethodV(this,obj,clazz, + methodID,args); + va_end(args); + return result; + } + jbyte CallNonvirtualByteMethodV(jobject obj, jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallNonvirtualByteMethodV(this,obj,clazz, + methodID,args); + } + jbyte CallNonvirtualByteMethodA(jobject obj, jclass clazz, + jmethodID methodID, const jvalue * args) { + return functions->CallNonvirtualByteMethodA(this,obj,clazz, + methodID,args); + } + + jchar CallNonvirtualCharMethod(jobject obj, jclass clazz, + jmethodID methodID, ...) { + va_list args; + jchar result; + va_start(args,methodID); + result = functions->CallNonvirtualCharMethodV(this,obj,clazz, + methodID,args); + va_end(args); + return result; + } + jchar CallNonvirtualCharMethodV(jobject obj, jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallNonvirtualCharMethodV(this,obj,clazz, + methodID,args); + } + jchar CallNonvirtualCharMethodA(jobject obj, jclass clazz, + jmethodID methodID, const jvalue * args) { + return functions->CallNonvirtualCharMethodA(this,obj,clazz, + methodID,args); + } + + jshort CallNonvirtualShortMethod(jobject obj, jclass clazz, + jmethodID methodID, ...) { + va_list args; + jshort result; + va_start(args,methodID); + result = functions->CallNonvirtualShortMethodV(this,obj,clazz, + methodID,args); + va_end(args); + return result; + } + jshort CallNonvirtualShortMethodV(jobject obj, jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallNonvirtualShortMethodV(this,obj,clazz, + methodID,args); + } + jshort CallNonvirtualShortMethodA(jobject obj, jclass clazz, + jmethodID methodID, const jvalue * args) { + return functions->CallNonvirtualShortMethodA(this,obj,clazz, + methodID,args); + } + + jint CallNonvirtualIntMethod(jobject obj, jclass clazz, + jmethodID methodID, ...) { + va_list args; + jint result; + va_start(args,methodID); + result = functions->CallNonvirtualIntMethodV(this,obj,clazz, + methodID,args); + va_end(args); + return result; + } + jint CallNonvirtualIntMethodV(jobject obj, jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallNonvirtualIntMethodV(this,obj,clazz, + methodID,args); + } + jint CallNonvirtualIntMethodA(jobject obj, jclass clazz, + jmethodID methodID, const jvalue * args) { + return functions->CallNonvirtualIntMethodA(this,obj,clazz, + methodID,args); + } + + jlong CallNonvirtualLongMethod(jobject obj, jclass clazz, + jmethodID methodID, ...) { + va_list args; + jlong result; + va_start(args,methodID); + result = functions->CallNonvirtualLongMethodV(this,obj,clazz, + methodID,args); + va_end(args); + return result; + } + jlong CallNonvirtualLongMethodV(jobject obj, jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallNonvirtualLongMethodV(this,obj,clazz, + methodID,args); + } + jlong CallNonvirtualLongMethodA(jobject obj, jclass clazz, + jmethodID methodID, const jvalue * args) { + return functions->CallNonvirtualLongMethodA(this,obj,clazz, + methodID,args); + } + + jfloat CallNonvirtualFloatMethod(jobject obj, jclass clazz, + jmethodID methodID, ...) { + va_list args; + jfloat result; + va_start(args,methodID); + result = functions->CallNonvirtualFloatMethodV(this,obj,clazz, + methodID,args); + va_end(args); + return result; + } + jfloat CallNonvirtualFloatMethodV(jobject obj, jclass clazz, + jmethodID methodID, + va_list args) { + return functions->CallNonvirtualFloatMethodV(this,obj,clazz, + methodID,args); + } + jfloat CallNonvirtualFloatMethodA(jobject obj, jclass clazz, + jmethodID methodID, + const jvalue * args) { + return functions->CallNonvirtualFloatMethodA(this,obj,clazz, + methodID,args); + } + + jdouble CallNonvirtualDoubleMethod(jobject obj, jclass clazz, + jmethodID methodID, ...) { + va_list args; + jdouble result; + va_start(args,methodID); + result = functions->CallNonvirtualDoubleMethodV(this,obj,clazz, + methodID,args); + va_end(args); + return result; + } + jdouble CallNonvirtualDoubleMethodV(jobject obj, jclass clazz, + jmethodID methodID, + va_list args) { + return functions->CallNonvirtualDoubleMethodV(this,obj,clazz, + methodID,args); + } + jdouble CallNonvirtualDoubleMethodA(jobject obj, jclass clazz, + jmethodID methodID, + const jvalue * args) { + return functions->CallNonvirtualDoubleMethodA(this,obj,clazz, + methodID,args); + } + + void CallNonvirtualVoidMethod(jobject obj, jclass clazz, + jmethodID methodID, ...) { + va_list args; + va_start(args,methodID); + functions->CallNonvirtualVoidMethodV(this,obj,clazz,methodID,args); + va_end(args); + } + void CallNonvirtualVoidMethodV(jobject obj, jclass clazz, + jmethodID methodID, + va_list args) { + functions->CallNonvirtualVoidMethodV(this,obj,clazz,methodID,args); + } + void CallNonvirtualVoidMethodA(jobject obj, jclass clazz, + jmethodID methodID, + const jvalue * args) { + functions->CallNonvirtualVoidMethodA(this,obj,clazz,methodID,args); + } + + jfieldID GetFieldID(jclass clazz, const char *name, + const char *sig) { + return functions->GetFieldID(this,clazz,name,sig); + } + + jobject GetObjectField(jobject obj, jfieldID fieldID) { + return functions->GetObjectField(this,obj,fieldID); + } + jboolean GetBooleanField(jobject obj, jfieldID fieldID) { + return functions->GetBooleanField(this,obj,fieldID); + } + jbyte GetByteField(jobject obj, jfieldID fieldID) { + return functions->GetByteField(this,obj,fieldID); + } + jchar GetCharField(jobject obj, jfieldID fieldID) { + return functions->GetCharField(this,obj,fieldID); + } + jshort GetShortField(jobject obj, jfieldID fieldID) { + return functions->GetShortField(this,obj,fieldID); + } + jint GetIntField(jobject obj, jfieldID fieldID) { + return functions->GetIntField(this,obj,fieldID); + } + jlong GetLongField(jobject obj, jfieldID fieldID) { + return functions->GetLongField(this,obj,fieldID); + } + jfloat GetFloatField(jobject obj, jfieldID fieldID) { + return functions->GetFloatField(this,obj,fieldID); + } + jdouble GetDoubleField(jobject obj, jfieldID fieldID) { + return functions->GetDoubleField(this,obj,fieldID); + } + + void SetObjectField(jobject obj, jfieldID fieldID, jobject val) { + functions->SetObjectField(this,obj,fieldID,val); + } + void SetBooleanField(jobject obj, jfieldID fieldID, + jboolean val) { + functions->SetBooleanField(this,obj,fieldID,val); + } + void SetByteField(jobject obj, jfieldID fieldID, + jbyte val) { + functions->SetByteField(this,obj,fieldID,val); + } + void SetCharField(jobject obj, jfieldID fieldID, + jchar val) { + functions->SetCharField(this,obj,fieldID,val); + } + void SetShortField(jobject obj, jfieldID fieldID, + jshort val) { + functions->SetShortField(this,obj,fieldID,val); + } + void SetIntField(jobject obj, jfieldID fieldID, + jint val) { + functions->SetIntField(this,obj,fieldID,val); + } + void SetLongField(jobject obj, jfieldID fieldID, + jlong val) { + functions->SetLongField(this,obj,fieldID,val); + } + void SetFloatField(jobject obj, jfieldID fieldID, + jfloat val) { + functions->SetFloatField(this,obj,fieldID,val); + } + void SetDoubleField(jobject obj, jfieldID fieldID, + jdouble val) { + functions->SetDoubleField(this,obj,fieldID,val); + } + + jmethodID GetStaticMethodID(jclass clazz, const char *name, + const char *sig) { + return functions->GetStaticMethodID(this,clazz,name,sig); + } + + jobject CallStaticObjectMethod(jclass clazz, jmethodID methodID, + ...) { + va_list args; + jobject result; + va_start(args,methodID); + result = functions->CallStaticObjectMethodV(this,clazz,methodID,args); + va_end(args); + return result; + } + jobject CallStaticObjectMethodV(jclass clazz, jmethodID methodID, + va_list args) { + return functions->CallStaticObjectMethodV(this,clazz,methodID,args); + } + jobject CallStaticObjectMethodA(jclass clazz, jmethodID methodID, + const jvalue *args) { + return functions->CallStaticObjectMethodA(this,clazz,methodID,args); + } + + jboolean CallStaticBooleanMethod(jclass clazz, + jmethodID methodID, ...) { + va_list args; + jboolean result; + va_start(args,methodID); + result = functions->CallStaticBooleanMethodV(this,clazz,methodID,args); + va_end(args); + return result; + } + jboolean CallStaticBooleanMethodV(jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallStaticBooleanMethodV(this,clazz,methodID,args); + } + jboolean CallStaticBooleanMethodA(jclass clazz, + jmethodID methodID, const jvalue *args) { + return functions->CallStaticBooleanMethodA(this,clazz,methodID,args); + } + + jbyte CallStaticByteMethod(jclass clazz, + jmethodID methodID, ...) { + va_list args; + jbyte result; + va_start(args,methodID); + result = functions->CallStaticByteMethodV(this,clazz,methodID,args); + va_end(args); + return result; + } + jbyte CallStaticByteMethodV(jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallStaticByteMethodV(this,clazz,methodID,args); + } + jbyte CallStaticByteMethodA(jclass clazz, + jmethodID methodID, const jvalue *args) { + return functions->CallStaticByteMethodA(this,clazz,methodID,args); + } + + jchar CallStaticCharMethod(jclass clazz, + jmethodID methodID, ...) { + va_list args; + jchar result; + va_start(args,methodID); + result = functions->CallStaticCharMethodV(this,clazz,methodID,args); + va_end(args); + return result; + } + jchar CallStaticCharMethodV(jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallStaticCharMethodV(this,clazz,methodID,args); + } + jchar CallStaticCharMethodA(jclass clazz, + jmethodID methodID, const jvalue *args) { + return functions->CallStaticCharMethodA(this,clazz,methodID,args); + } + + jshort CallStaticShortMethod(jclass clazz, + jmethodID methodID, ...) { + va_list args; + jshort result; + va_start(args,methodID); + result = functions->CallStaticShortMethodV(this,clazz,methodID,args); + va_end(args); + return result; + } + jshort CallStaticShortMethodV(jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallStaticShortMethodV(this,clazz,methodID,args); + } + jshort CallStaticShortMethodA(jclass clazz, + jmethodID methodID, const jvalue *args) { + return functions->CallStaticShortMethodA(this,clazz,methodID,args); + } + + jint CallStaticIntMethod(jclass clazz, + jmethodID methodID, ...) { + va_list args; + jint result; + va_start(args,methodID); + result = functions->CallStaticIntMethodV(this,clazz,methodID,args); + va_end(args); + return result; + } + jint CallStaticIntMethodV(jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallStaticIntMethodV(this,clazz,methodID,args); + } + jint CallStaticIntMethodA(jclass clazz, + jmethodID methodID, const jvalue *args) { + return functions->CallStaticIntMethodA(this,clazz,methodID,args); + } + + jlong CallStaticLongMethod(jclass clazz, + jmethodID methodID, ...) { + va_list args; + jlong result; + va_start(args,methodID); + result = functions->CallStaticLongMethodV(this,clazz,methodID,args); + va_end(args); + return result; + } + jlong CallStaticLongMethodV(jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallStaticLongMethodV(this,clazz,methodID,args); + } + jlong CallStaticLongMethodA(jclass clazz, + jmethodID methodID, const jvalue *args) { + return functions->CallStaticLongMethodA(this,clazz,methodID,args); + } + + jfloat CallStaticFloatMethod(jclass clazz, + jmethodID methodID, ...) { + va_list args; + jfloat result; + va_start(args,methodID); + result = functions->CallStaticFloatMethodV(this,clazz,methodID,args); + va_end(args); + return result; + } + jfloat CallStaticFloatMethodV(jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallStaticFloatMethodV(this,clazz,methodID,args); + } + jfloat CallStaticFloatMethodA(jclass clazz, + jmethodID methodID, const jvalue *args) { + return functions->CallStaticFloatMethodA(this,clazz,methodID,args); + } + + jdouble CallStaticDoubleMethod(jclass clazz, + jmethodID methodID, ...) { + va_list args; + jdouble result; + va_start(args,methodID); + result = functions->CallStaticDoubleMethodV(this,clazz,methodID,args); + va_end(args); + return result; + } + jdouble CallStaticDoubleMethodV(jclass clazz, + jmethodID methodID, va_list args) { + return functions->CallStaticDoubleMethodV(this,clazz,methodID,args); + } + jdouble CallStaticDoubleMethodA(jclass clazz, + jmethodID methodID, const jvalue *args) { + return functions->CallStaticDoubleMethodA(this,clazz,methodID,args); + } + + void CallStaticVoidMethod(jclass cls, jmethodID methodID, ...) { + va_list args; + va_start(args,methodID); + functions->CallStaticVoidMethodV(this,cls,methodID,args); + va_end(args); + } + void CallStaticVoidMethodV(jclass cls, jmethodID methodID, + va_list args) { + functions->CallStaticVoidMethodV(this,cls,methodID,args); + } + void CallStaticVoidMethodA(jclass cls, jmethodID methodID, + const jvalue * args) { + functions->CallStaticVoidMethodA(this,cls,methodID,args); + } + + jfieldID GetStaticFieldID(jclass clazz, const char *name, + const char *sig) { + return functions->GetStaticFieldID(this,clazz,name,sig); + } + jobject GetStaticObjectField(jclass clazz, jfieldID fieldID) { + return functions->GetStaticObjectField(this,clazz,fieldID); + } + jboolean GetStaticBooleanField(jclass clazz, jfieldID fieldID) { + return functions->GetStaticBooleanField(this,clazz,fieldID); + } + jbyte GetStaticByteField(jclass clazz, jfieldID fieldID) { + return functions->GetStaticByteField(this,clazz,fieldID); + } + jchar GetStaticCharField(jclass clazz, jfieldID fieldID) { + return functions->GetStaticCharField(this,clazz,fieldID); + } + jshort GetStaticShortField(jclass clazz, jfieldID fieldID) { + return functions->GetStaticShortField(this,clazz,fieldID); + } + jint GetStaticIntField(jclass clazz, jfieldID fieldID) { + return functions->GetStaticIntField(this,clazz,fieldID); + } + jlong GetStaticLongField(jclass clazz, jfieldID fieldID) { + return functions->GetStaticLongField(this,clazz,fieldID); + } + jfloat GetStaticFloatField(jclass clazz, jfieldID fieldID) { + return functions->GetStaticFloatField(this,clazz,fieldID); + } + jdouble GetStaticDoubleField(jclass clazz, jfieldID fieldID) { + return functions->GetStaticDoubleField(this,clazz,fieldID); + } + + void SetStaticObjectField(jclass clazz, jfieldID fieldID, + jobject value) { + functions->SetStaticObjectField(this,clazz,fieldID,value); + } + void SetStaticBooleanField(jclass clazz, jfieldID fieldID, + jboolean value) { + functions->SetStaticBooleanField(this,clazz,fieldID,value); + } + void SetStaticByteField(jclass clazz, jfieldID fieldID, + jbyte value) { + functions->SetStaticByteField(this,clazz,fieldID,value); + } + void SetStaticCharField(jclass clazz, jfieldID fieldID, + jchar value) { + functions->SetStaticCharField(this,clazz,fieldID,value); + } + void SetStaticShortField(jclass clazz, jfieldID fieldID, + jshort value) { + functions->SetStaticShortField(this,clazz,fieldID,value); + } + void SetStaticIntField(jclass clazz, jfieldID fieldID, + jint value) { + functions->SetStaticIntField(this,clazz,fieldID,value); + } + void SetStaticLongField(jclass clazz, jfieldID fieldID, + jlong value) { + functions->SetStaticLongField(this,clazz,fieldID,value); + } + void SetStaticFloatField(jclass clazz, jfieldID fieldID, + jfloat value) { + functions->SetStaticFloatField(this,clazz,fieldID,value); + } + void SetStaticDoubleField(jclass clazz, jfieldID fieldID, + jdouble value) { + functions->SetStaticDoubleField(this,clazz,fieldID,value); + } + + jstring NewString(const jchar *unicode, jsize len) { + return functions->NewString(this,unicode,len); + } + jsize GetStringLength(jstring str) { + return functions->GetStringLength(this,str); + } + const jchar *GetStringChars(jstring str, jboolean *isCopy) { + return functions->GetStringChars(this,str,isCopy); + } + void ReleaseStringChars(jstring str, const jchar *chars) { + functions->ReleaseStringChars(this,str,chars); + } + + jstring NewStringUTF(const char *utf) { + return functions->NewStringUTF(this,utf); + } + jsize GetStringUTFLength(jstring str) { + return functions->GetStringUTFLength(this,str); + } + const char* GetStringUTFChars(jstring str, jboolean *isCopy) { + return functions->GetStringUTFChars(this,str,isCopy); + } + void ReleaseStringUTFChars(jstring str, const char* chars) { + functions->ReleaseStringUTFChars(this,str,chars); + } + + jsize GetArrayLength(jarray array) { + return functions->GetArrayLength(this,array); + } + + jobjectArray NewObjectArray(jsize len, jclass clazz, + jobject init) { + return functions->NewObjectArray(this,len,clazz,init); + } + jobject GetObjectArrayElement(jobjectArray array, jsize index) { + return functions->GetObjectArrayElement(this,array,index); + } + void SetObjectArrayElement(jobjectArray array, jsize index, + jobject val) { + functions->SetObjectArrayElement(this,array,index,val); + } + + jbooleanArray NewBooleanArray(jsize len) { + return functions->NewBooleanArray(this,len); + } + jbyteArray NewByteArray(jsize len) { + return functions->NewByteArray(this,len); + } + jcharArray NewCharArray(jsize len) { + return functions->NewCharArray(this,len); + } + jshortArray NewShortArray(jsize len) { + return functions->NewShortArray(this,len); + } + jintArray NewIntArray(jsize len) { + return functions->NewIntArray(this,len); + } + jlongArray NewLongArray(jsize len) { + return functions->NewLongArray(this,len); + } + jfloatArray NewFloatArray(jsize len) { + return functions->NewFloatArray(this,len); + } + jdoubleArray NewDoubleArray(jsize len) { + return functions->NewDoubleArray(this,len); + } + + jboolean * GetBooleanArrayElements(jbooleanArray array, jboolean *isCopy) { + return functions->GetBooleanArrayElements(this,array,isCopy); + } + jbyte * GetByteArrayElements(jbyteArray array, jboolean *isCopy) { + return functions->GetByteArrayElements(this,array,isCopy); + } + jchar * GetCharArrayElements(jcharArray array, jboolean *isCopy) { + return functions->GetCharArrayElements(this,array,isCopy); + } + jshort * GetShortArrayElements(jshortArray array, jboolean *isCopy) { + return functions->GetShortArrayElements(this,array,isCopy); + } + jint * GetIntArrayElements(jintArray array, jboolean *isCopy) { + return functions->GetIntArrayElements(this,array,isCopy); + } + jlong * GetLongArrayElements(jlongArray array, jboolean *isCopy) { + return functions->GetLongArrayElements(this,array,isCopy); + } + jfloat * GetFloatArrayElements(jfloatArray array, jboolean *isCopy) { + return functions->GetFloatArrayElements(this,array,isCopy); + } + jdouble * GetDoubleArrayElements(jdoubleArray array, jboolean *isCopy) { + return functions->GetDoubleArrayElements(this,array,isCopy); + } + + void ReleaseBooleanArrayElements(jbooleanArray array, + jboolean *elems, + jint mode) { + functions->ReleaseBooleanArrayElements(this,array,elems,mode); + } + void ReleaseByteArrayElements(jbyteArray array, + jbyte *elems, + jint mode) { + functions->ReleaseByteArrayElements(this,array,elems,mode); + } + void ReleaseCharArrayElements(jcharArray array, + jchar *elems, + jint mode) { + functions->ReleaseCharArrayElements(this,array,elems,mode); + } + void ReleaseShortArrayElements(jshortArray array, + jshort *elems, + jint mode) { + functions->ReleaseShortArrayElements(this,array,elems,mode); + } + void ReleaseIntArrayElements(jintArray array, + jint *elems, + jint mode) { + functions->ReleaseIntArrayElements(this,array,elems,mode); + } + void ReleaseLongArrayElements(jlongArray array, + jlong *elems, + jint mode) { + functions->ReleaseLongArrayElements(this,array,elems,mode); + } + void ReleaseFloatArrayElements(jfloatArray array, + jfloat *elems, + jint mode) { + functions->ReleaseFloatArrayElements(this,array,elems,mode); + } + void ReleaseDoubleArrayElements(jdoubleArray array, + jdouble *elems, + jint mode) { + functions->ReleaseDoubleArrayElements(this,array,elems,mode); + } + + void GetBooleanArrayRegion(jbooleanArray array, + jsize start, jsize len, jboolean *buf) { + functions->GetBooleanArrayRegion(this,array,start,len,buf); + } + void GetByteArrayRegion(jbyteArray array, + jsize start, jsize len, jbyte *buf) { + functions->GetByteArrayRegion(this,array,start,len,buf); + } + void GetCharArrayRegion(jcharArray array, + jsize start, jsize len, jchar *buf) { + functions->GetCharArrayRegion(this,array,start,len,buf); + } + void GetShortArrayRegion(jshortArray array, + jsize start, jsize len, jshort *buf) { + functions->GetShortArrayRegion(this,array,start,len,buf); + } + void GetIntArrayRegion(jintArray array, + jsize start, jsize len, jint *buf) { + functions->GetIntArrayRegion(this,array,start,len,buf); + } + void GetLongArrayRegion(jlongArray array, + jsize start, jsize len, jlong *buf) { + functions->GetLongArrayRegion(this,array,start,len,buf); + } + void GetFloatArrayRegion(jfloatArray array, + jsize start, jsize len, jfloat *buf) { + functions->GetFloatArrayRegion(this,array,start,len,buf); + } + void GetDoubleArrayRegion(jdoubleArray array, + jsize start, jsize len, jdouble *buf) { + functions->GetDoubleArrayRegion(this,array,start,len,buf); + } + + void SetBooleanArrayRegion(jbooleanArray array, jsize start, jsize len, + const jboolean *buf) { + functions->SetBooleanArrayRegion(this,array,start,len,buf); + } + void SetByteArrayRegion(jbyteArray array, jsize start, jsize len, + const jbyte *buf) { + functions->SetByteArrayRegion(this,array,start,len,buf); + } + void SetCharArrayRegion(jcharArray array, jsize start, jsize len, + const jchar *buf) { + functions->SetCharArrayRegion(this,array,start,len,buf); + } + void SetShortArrayRegion(jshortArray array, jsize start, jsize len, + const jshort *buf) { + functions->SetShortArrayRegion(this,array,start,len,buf); + } + void SetIntArrayRegion(jintArray array, jsize start, jsize len, + const jint *buf) { + functions->SetIntArrayRegion(this,array,start,len,buf); + } + void SetLongArrayRegion(jlongArray array, jsize start, jsize len, + const jlong *buf) { + functions->SetLongArrayRegion(this,array,start,len,buf); + } + void SetFloatArrayRegion(jfloatArray array, jsize start, jsize len, + const jfloat *buf) { + functions->SetFloatArrayRegion(this,array,start,len,buf); + } + void SetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len, + const jdouble *buf) { + functions->SetDoubleArrayRegion(this,array,start,len,buf); + } + + jint RegisterNatives(jclass clazz, const JNINativeMethod *methods, + jint nMethods) { + return functions->RegisterNatives(this,clazz,methods,nMethods); + } + jint UnregisterNatives(jclass clazz) { + return functions->UnregisterNatives(this,clazz); + } + + jint MonitorEnter(jobject obj) { + return functions->MonitorEnter(this,obj); + } + jint MonitorExit(jobject obj) { + return functions->MonitorExit(this,obj); + } + + jint GetJavaVM(JavaVM **vm) { + return functions->GetJavaVM(this,vm); + } + + void GetStringRegion(jstring str, jsize start, jsize len, jchar *buf) { + functions->GetStringRegion(this,str,start,len,buf); + } + void GetStringUTFRegion(jstring str, jsize start, jsize len, char *buf) { + functions->GetStringUTFRegion(this,str,start,len,buf); + } + + void * GetPrimitiveArrayCritical(jarray array, jboolean *isCopy) { + return functions->GetPrimitiveArrayCritical(this,array,isCopy); + } + void ReleasePrimitiveArrayCritical(jarray array, void *carray, jint mode) { + functions->ReleasePrimitiveArrayCritical(this,array,carray,mode); + } + + const jchar * GetStringCritical(jstring string, jboolean *isCopy) { + return functions->GetStringCritical(this,string,isCopy); + } + void ReleaseStringCritical(jstring string, const jchar *cstring) { + functions->ReleaseStringCritical(this,string,cstring); + } + + jweak NewWeakGlobalRef(jobject obj) { + return functions->NewWeakGlobalRef(this,obj); + } + void DeleteWeakGlobalRef(jweak ref) { + functions->DeleteWeakGlobalRef(this,ref); + } + + jboolean ExceptionCheck() { + return functions->ExceptionCheck(this); + } + + jobject NewDirectByteBuffer(void* address, jlong capacity) { + return functions->NewDirectByteBuffer(this, address, capacity); + } + void* GetDirectBufferAddress(jobject buf) { + return functions->GetDirectBufferAddress(this, buf); + } + jlong GetDirectBufferCapacity(jobject buf) { + return functions->GetDirectBufferCapacity(this, buf); + } + jobjectRefType GetObjectRefType(jobject obj) { + return functions->GetObjectRefType(this, obj); + } + + /* Module Features */ + + jobject GetModule(jclass clazz) { + return functions->GetModule(this, clazz); + } + + /* Virtual threads */ + + jboolean IsVirtualThread(jobject obj) { + return functions->IsVirtualThread(this, obj); + } + +#endif /* __cplusplus */ +}; + +/* + * optionString may be any option accepted by the JVM, or one of the + * following: + * + * -D= Set a system property. + * -verbose[:class|gc|jni] Enable verbose output, comma-separated. E.g. + * "-verbose:class" or "-verbose:gc,class" + * Standard names include: gc, class, and jni. + * All nonstandard (VM-specific) names must begin + * with "X". + * vfprintf extraInfo is a pointer to the vfprintf hook. + * exit extraInfo is a pointer to the exit hook. + * abort extraInfo is a pointer to the abort hook. + */ +typedef struct JavaVMOption { + char *optionString; + void *extraInfo; +} JavaVMOption; + +typedef struct JavaVMInitArgs { + jint version; + + jint nOptions; + JavaVMOption *options; + jboolean ignoreUnrecognized; +} JavaVMInitArgs; + +typedef struct JavaVMAttachArgs { + jint version; + + char *name; + jobject group; +} JavaVMAttachArgs; + +/* These will be VM-specific. */ + +#define JDK1_2 +#define JDK1_4 + +/* End VM-specific. */ + +struct JNIInvokeInterface_ { + void *reserved0; + void *reserved1; + void *reserved2; + + jint (JNICALL *DestroyJavaVM)(JavaVM *vm); + + jint (JNICALL *AttachCurrentThread)(JavaVM *vm, void **penv, void *args); + + jint (JNICALL *DetachCurrentThread)(JavaVM *vm); + + jint (JNICALL *GetEnv)(JavaVM *vm, void **penv, jint version); + + jint (JNICALL *AttachCurrentThreadAsDaemon)(JavaVM *vm, void **penv, void *args); +}; + +struct JavaVM_ { + const struct JNIInvokeInterface_ *functions; +#ifdef __cplusplus + + jint DestroyJavaVM() { + return functions->DestroyJavaVM(this); + } + jint AttachCurrentThread(void **penv, void *args) { + return functions->AttachCurrentThread(this, penv, args); + } + jint DetachCurrentThread() { + return functions->DetachCurrentThread(this); + } + + jint GetEnv(void **penv, jint version) { + return functions->GetEnv(this, penv, version); + } + jint AttachCurrentThreadAsDaemon(void **penv, void *args) { + return functions->AttachCurrentThreadAsDaemon(this, penv, args); + } +#endif +}; + +#ifdef _JNI_IMPLEMENTATION_ +#define _JNI_IMPORT_OR_EXPORT_ JNIEXPORT +#else +#define _JNI_IMPORT_OR_EXPORT_ JNIIMPORT +#endif +_JNI_IMPORT_OR_EXPORT_ jint JNICALL +JNI_GetDefaultJavaVMInitArgs(void *args); + +_JNI_IMPORT_OR_EXPORT_ jint JNICALL +JNI_CreateJavaVM(JavaVM **pvm, void **penv, void *args); + +_JNI_IMPORT_OR_EXPORT_ jint JNICALL +JNI_GetCreatedJavaVMs(JavaVM **, jsize, jsize *); + +/* Defined by native libraries. */ +JNIEXPORT jint JNICALL +JNI_OnLoad(JavaVM *vm, void *reserved); + +JNIEXPORT void JNICALL +JNI_OnUnload(JavaVM *vm, void *reserved); + +#define JNI_VERSION_1_1 0x00010001 +#define JNI_VERSION_1_2 0x00010002 +#define JNI_VERSION_1_4 0x00010004 +#define JNI_VERSION_1_6 0x00010006 +#define JNI_VERSION_1_8 0x00010008 +#define JNI_VERSION_9 0x00090000 +#define JNI_VERSION_10 0x000a0000 +#define JNI_VERSION_19 0x00130000 +#define JNI_VERSION_20 0x00140000 +#define JNI_VERSION_21 0x00150000 + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* !_JAVASOFT_JNI_H_ */ diff --git a/apps/multiplatform/common/src/commonMain/cpp/desktop/include/unix/jni_md.h b/apps/multiplatform/common/src/commonMain/cpp/desktop/include/unix/jni_md.h new file mode 100644 index 000000000..6e583da71 --- /dev/null +++ b/apps/multiplatform/common/src/commonMain/cpp/desktop/include/unix/jni_md.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef _JAVASOFT_JNI_MD_H_ +#define _JAVASOFT_JNI_MD_H_ + +#ifndef __has_attribute + #define __has_attribute(x) 0 +#endif + +#ifndef JNIEXPORT + #if (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ > 2))) || __has_attribute(visibility) + #ifdef ARM + #define JNIEXPORT __attribute__((externally_visible,visibility("default"))) + #else + #define JNIEXPORT __attribute__((visibility("default"))) + #endif + #else + #define JNIEXPORT + #endif +#endif + +#if (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ > 2))) || __has_attribute(visibility) + #ifdef ARM + #define JNIIMPORT __attribute__((externally_visible,visibility("default"))) + #else + #define JNIIMPORT __attribute__((visibility("default"))) + #endif +#else + #define JNIIMPORT +#endif + +#define JNICALL + +typedef int jint; +#ifdef _LP64 +typedef long jlong; +#else +typedef long long jlong; +#endif + +typedef signed char jbyte; + +#endif /* !_JAVASOFT_JNI_MD_H_ */ diff --git a/apps/multiplatform/common/src/commonMain/cpp/desktop/include/windows/jni_md.h b/apps/multiplatform/common/src/commonMain/cpp/desktop/include/windows/jni_md.h new file mode 100644 index 000000000..b8c144fb0 --- /dev/null +++ b/apps/multiplatform/common/src/commonMain/cpp/desktop/include/windows/jni_md.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef _JAVASOFT_JNI_MD_H_ +#define _JAVASOFT_JNI_MD_H_ + +#ifndef JNIEXPORT + #define JNIEXPORT __declspec(dllexport) +#endif +#define JNIIMPORT __declspec(dllimport) +#define JNICALL __stdcall + +// 'long' is always 32 bit on windows so this matches what jdk expects +typedef long jint; +typedef __int64 jlong; +typedef signed char jbyte; + +#endif /* !_JAVASOFT_JNI_MD_H_ */ diff --git a/apps/multiplatform/common/src/commonMain/cpp/desktop/simplex-api.c b/apps/multiplatform/common/src/commonMain/cpp/desktop/simplex-api.c new file mode 100644 index 000000000..e772adffa --- /dev/null +++ b/apps/multiplatform/common/src/commonMain/cpp/desktop/simplex-api.c @@ -0,0 +1,98 @@ +#include + +// from the RTS +void hs_init(int * argc, char **argv[]); + +//extern void __svfscanf(void){}; +//extern void __vfwscanf(void){}; +//extern void __memset_chk_fail(void){}; +//extern void __strcpy_chk_generic(void){}; +//extern void __strcat_chk_generic(void){}; +//extern void __libc_globals(void){}; +//extern void __rel_iplt_start(void){}; + +// Android 9 only, not 13 +//extern void reallocarray(void){}; + +JNIEXPORT void JNICALL +Java_chat_simplex_common_platform_BackendKt_initHS(JNIEnv *env, jclass clazz) { + hs_init(NULL, NULL); +} + +// from simplex-chat +typedef long* chat_ctrl; + +extern char *chat_migrate_init(const char *path, const char *key, const char *confirm, chat_ctrl *ctrl); +extern char *chat_send_cmd(chat_ctrl ctrl, const char *cmd); +extern char *chat_recv_msg(chat_ctrl ctrl); // deprecated +extern char *chat_recv_msg_wait(chat_ctrl ctrl, const int wait); +extern char *chat_parse_markdown(const char *str); +extern char *chat_parse_server(const char *str); +extern char *chat_password_hash(const char *pwd, const char *salt); + +JNIEXPORT jobjectArray JNICALL +Java_chat_simplex_common_platform_BackendKt_chatMigrateInit(JNIEnv *env, jclass clazz, jstring dbPath, jstring dbKey, jstring confirm) { + const char *_dbPath = (*env)->GetStringUTFChars(env, dbPath, JNI_FALSE); + const char *_dbKey = (*env)->GetStringUTFChars(env, dbKey, JNI_FALSE); + const char *_confirm = (*env)->GetStringUTFChars(env, confirm, JNI_FALSE); + jlong _ctrl = (jlong) 0; + jstring res = (*env)->NewStringUTF(env, chat_migrate_init(_dbPath, _dbKey, _confirm, &_ctrl)); + (*env)->ReleaseStringUTFChars(env, dbPath, _dbPath); + (*env)->ReleaseStringUTFChars(env, dbKey, _dbKey); + (*env)->ReleaseStringUTFChars(env, dbKey, _confirm); + + // Creating array of Object's (boxed values can be passed, eg. Long instead of long) + jobjectArray ret = (jobjectArray)(*env)->NewObjectArray(env, 2, (*env)->FindClass(env, "java/lang/Object"), NULL); + // Java's String + (*env)->SetObjectArrayElement(env, ret, 0, res); + // Java's Long + (*env)->SetObjectArrayElement(env, ret, 1, + (*env)->NewObject(env, (*env)->FindClass(env, "java/lang/Long"), + (*env)->GetMethodID(env, (*env)->FindClass(env, "java/lang/Long"), "", "(J)V"), + _ctrl)); + return ret; +} + +JNIEXPORT jstring JNICALL +Java_chat_simplex_common_platform_BackendKt_chatSendCmd(JNIEnv *env, jclass clazz, jlong controller, jstring msg) { + const char *_msg = (*env)->GetStringUTFChars(env, msg, JNI_FALSE); + jstring res = (*env)->NewStringUTF(env, chat_send_cmd((void*)controller, _msg)); + (*env)->ReleaseStringUTFChars(env, msg, _msg); + return res; +} + +JNIEXPORT jstring JNICALL +Java_chat_simplex_common_platform_BackendKt_chatRecvMsg(JNIEnv *env, jclass clazz, jlong controller) { + return (*env)->NewStringUTF(env, chat_recv_msg((void*)controller)); +} + +JNIEXPORT jstring JNICALL +Java_chat_simplex_common_platform_BackendKt_chatRecvMsgWait(JNIEnv *env, jclass clazz, jlong controller, jint wait) { + return (*env)->NewStringUTF(env, chat_recv_msg_wait((void*)controller, wait)); +} + +JNIEXPORT jstring JNICALL +Java_chat_simplex_common_platform_BackendKt_chatParseMarkdown(JNIEnv *env, jclass clazz, jstring str) { + const char *_str = (*env)->GetStringUTFChars(env, str, JNI_FALSE); + jstring res = (*env)->NewStringUTF(env, chat_parse_markdown(_str)); + (*env)->ReleaseStringUTFChars(env, str, _str); + return res; +} + +JNIEXPORT jstring JNICALL +Java_chat_simplex_common_platform_BackendKt_chatParseServer(JNIEnv *env, jclass clazz, jstring str) { + const char *_str = (*env)->GetStringUTFChars(env, str, JNI_FALSE); + jstring res = (*env)->NewStringUTF(env, chat_parse_server(_str)); + (*env)->ReleaseStringUTFChars(env, str, _str); + return res; +} + +JNIEXPORT jstring JNICALL +Java_chat_simplex_common_platform_BackendKt_chatPasswordHash(JNIEnv *env, jclass clazz, jstring pwd, jstring salt) { + const char *_pwd = (*env)->GetStringUTFChars(env, pwd, JNI_FALSE); + const char *_salt = (*env)->GetStringUTFChars(env, salt, JNI_FALSE); + jstring res = (*env)->NewStringUTF(env, chat_password_hash(_pwd, _salt)); + (*env)->ReleaseStringUTFChars(env, pwd, _pwd); + (*env)->ReleaseStringUTFChars(env, salt, _salt); + return res; +} diff --git a/apps/multiplatform/common/src/commonMain/cpp/desktop/toolchains/aarch64-linux-gnu-gcc.cmake b/apps/multiplatform/common/src/commonMain/cpp/desktop/toolchains/aarch64-linux-gnu-gcc.cmake new file mode 100644 index 000000000..4dd58aabf --- /dev/null +++ b/apps/multiplatform/common/src/commonMain/cpp/desktop/toolchains/aarch64-linux-gnu-gcc.cmake @@ -0,0 +1,20 @@ +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR aarch64) + +set(CMAKE_C_COMPILER "aarch64-linux-gnu-gcc") +set(CMAKE_CXX_COMPILER "aarch64-linux-gnu-g++") +set(CMAKE_AR "aarch64-linux-gnu-ar" CACHE FILEPATH Archiver) +set(CMAKE_RANLIB "aarch64-linux-gnu-ranlib" CACHE FILEPATH Indexer) + +set(CMAKE_FIND_ROOT_PATH /usr/aarch64-linux-gnu) + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +set(CMAKE_C_FLAGS "-march=armv8-a") +set(CMAKE_CXX_FLAGS "-march=armv8-a") + +# cache flags +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "c flags") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" CACHE STRING "c++ flags") diff --git a/apps/multiplatform/common/src/commonMain/cpp/desktop/toolchains/aarch64-mac-apple-darwin-gcc.cmake b/apps/multiplatform/common/src/commonMain/cpp/desktop/toolchains/aarch64-mac-apple-darwin-gcc.cmake new file mode 100644 index 000000000..f69e17306 --- /dev/null +++ b/apps/multiplatform/common/src/commonMain/cpp/desktop/toolchains/aarch64-mac-apple-darwin-gcc.cmake @@ -0,0 +1,17 @@ +set(CMAKE_SYSTEM_NAME Darwin) +set(CMAKE_SYSTEM_PROCESSOR aarch64) + +set(CMAKE_C_COMPILER "gcc-13") +set(CMAKE_CXX_COMPILER "g++-13") +set(CMAKE_AR "gcc-ar-13" CACHE FILEPATH Archiver) +set(CMAKE_RANLIB "gcc-ranlib-13" CACHE FILEPATH Indexer) + +set(CMAKE_FIND_ROOT_PATH /usr/) + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +# cache flags +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "c flags") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" CACHE STRING "c++ flags") diff --git a/apps/multiplatform/common/src/commonMain/cpp/desktop/toolchains/x86_64-linux-gnu-gcc.cmake b/apps/multiplatform/common/src/commonMain/cpp/desktop/toolchains/x86_64-linux-gnu-gcc.cmake new file mode 100644 index 000000000..e5dba4689 --- /dev/null +++ b/apps/multiplatform/common/src/commonMain/cpp/desktop/toolchains/x86_64-linux-gnu-gcc.cmake @@ -0,0 +1,17 @@ +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR amd64) + +set(CMAKE_C_COMPILER "x86_64-linux-gnu-gcc") +set(CMAKE_CXX_COMPILER "x86_64-linux-gnu-g++") +set(CMAKE_AR "x86_64-linux-gnu-gcc-ar" CACHE FILEPATH Archiver) +set(CMAKE_RANLIB "x86_64-linux-gnu-gcc-ranlib" CACHE FILEPATH Indexer) + +set(CMAKE_FIND_ROOT_PATH /usr/x86_64-linux-gnu) + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +# cache flags +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "c flags") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" CACHE STRING "c++ flags") diff --git a/apps/multiplatform/common/src/commonMain/cpp/desktop/toolchains/x86_64-mac-apple-darwin-gcc.cmake b/apps/multiplatform/common/src/commonMain/cpp/desktop/toolchains/x86_64-mac-apple-darwin-gcc.cmake new file mode 100644 index 000000000..a28b89d8a --- /dev/null +++ b/apps/multiplatform/common/src/commonMain/cpp/desktop/toolchains/x86_64-mac-apple-darwin-gcc.cmake @@ -0,0 +1,17 @@ +set(CMAKE_SYSTEM_NAME Darwin) +set(CMAKE_SYSTEM_PROCESSOR amd64) + +set(CMAKE_C_COMPILER "gcc-13") +set(CMAKE_CXX_COMPILER "g++-13") +set(CMAKE_AR "gcc-ar-13" CACHE FILEPATH Archiver) +set(CMAKE_RANLIB "gcc-ranlib-13" CACHE FILEPATH Indexer) + +set(CMAKE_FIND_ROOT_PATH /usr/) + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +# cache flags +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "c flags") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" CACHE STRING "c++ flags") diff --git a/apps/multiplatform/common/src/commonMain/cpp/desktop/toolchains/x86_64-windows-mingw32-gcc.cmake b/apps/multiplatform/common/src/commonMain/cpp/desktop/toolchains/x86_64-windows-mingw32-gcc.cmake new file mode 100644 index 000000000..e34e871b1 --- /dev/null +++ b/apps/multiplatform/common/src/commonMain/cpp/desktop/toolchains/x86_64-windows-mingw32-gcc.cmake @@ -0,0 +1,17 @@ +set(CMAKE_SYSTEM_NAME Windows) +set(CMAKE_SYSTEM_PROCESSOR amd64) + +set(CMAKE_C_COMPILER "x86_64-w64-mingw32-gcc") +set(CMAKE_CXX_COMPILER "x86_64-w64-mingw32-g++") +set(CMAKE_AR "x86_64-w64-mingw32-ar" CACHE FILEPATH Archiver) +set(CMAKE_RANLIB "x86_64-w64-mingw32-ranlib" CACHE FILEPATH Indexer) + +set(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32) + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +# cache flags +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "c flags") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" CACHE STRING "c++ flags") diff --git a/apps/multiplatform/desktop/build.gradle.kts b/apps/multiplatform/desktop/build.gradle.kts new file mode 100644 index 000000000..95a4908db --- /dev/null +++ b/apps/multiplatform/desktop/build.gradle.kts @@ -0,0 +1,169 @@ +import org.jetbrains.compose.desktop.application.dsl.TargetFormat + +plugins { + kotlin("multiplatform") + id("org.jetbrains.compose") + id("io.github.tomtzook.gradle-cmake") version "1.2.2" +} + +group = "chat.simplex" +version = extra["desktop.version_name"] as String + + +kotlin { + jvm { + jvmToolchain(11) + withJava() + } + sourceSets { + val jvmMain by getting { + dependencies { + implementation(project(":common")) + implementation(compose.desktop.currentOs) + } + } + val jvmTest by getting + } +} + +// https://github.com/JetBrains/compose-multiplatform/tree/master/tutorials/Native_distributions_and_local_execution +compose { + desktop { + application { + mainClass = "MainKt" + nativeDistributions { + modules("jdk.zipfs") + //includeAllModules = true + outputBaseDir.set(project.file("../release")) + targetFormats( + TargetFormat.Deb, TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Exe + //, TargetFormat.AppImage // Gradle doesn't sync on Mac with it + ) + linux { + iconFile.set(project.file("../common/src/commonMain/resources/distribute/simplex.png")) + appCategory = "Messenger" + } + windows { + // LALAL + iconFile.set(project.file("../common/src/commonMain/resources/distribute/simplex.ico")) + console = true + perUserInstall = true + dirChooser = true + } + macOS { + // LALAL + //iconFile.set(project.file("../common/src/commonMain/resources/distribute/simplex.icns")) + appCategory = "public.app-category.social-networking" + bundleID = "chat.simplex.app" + } + packageName = "simplex" + // Packaging requires to have version like MAJOR.MINOR.PATCH + var adjustedVersion = rootProject.extra["desktop.version_name"] as String + adjustedVersion = adjustedVersion.replace(Regex("[^0-9.]"), "") + if (adjustedVersion.split(".").size != 3) { + adjustedVersion += ".0" + } + version = adjustedVersion + } + } + } +} + +val cppPath = "../common/src/commonMain/cpp" +cmake { + // Run this command to make build for all targets: + // ./gradlew common:cmakeBuild -PcrossCompile + if (project.hasProperty("crossCompile")) { + machines.customMachines.register("linux-amd64") { + toolchainFile.set(project.file("$cppPath/toolchains/x86_64-linux-gnu-gcc.cmake")) + } + /*machines.customMachines.register("linux-aarch64") { + toolchainFile.set(project.file("$cppPath/toolchains/aarch64-linux-gnu-gcc.cmake")) + }*/ + machines.customMachines.register("win-amd64") { + toolchainFile.set(project.file("$cppPath/toolchains/x86_64-windows-mingw32-gcc.cmake")) + } + if (machines.host.name == "mac-amd64") { + machines.customMachines.register("mac-amd64") { + toolchainFile.set(project.file("$cppPath/toolchains/x86_64-mac-apple-darwin-gcc.cmake")) + } + } + if (machines.host.name == "mac-aarch64") { + machines.customMachines.register("mac-aarch64") { + toolchainFile.set(project.file("$cppPath/toolchains/aarch64-mac-apple-darwin-gcc.cmake")) + } + } + } + val compileMachineTargets = arrayListOf(machines.host) + compileMachineTargets.addAll(machines.customMachines) + targets { + val main by creating { + cmakeLists.set(file("$cppPath/desktop/CMakeLists.txt")) + targetMachines.addAll(compileMachineTargets.toSet()) + } + } +} + +tasks.named("clean") { + dependsOn("cmakeClean") +} +tasks.named("compileJava") { + dependsOn("cmakeBuildAndCopy") +} +afterEvaluate { + tasks.create("cmakeBuildAndCopy") { + dependsOn("cmakeBuild") + doLast { + copy { + from("${project(":desktop").buildDir}/cmake/main/linux-amd64", "$cppPath/desktop/libs/linux-x86_64", "$cppPath/desktop/libs/linux-x86_64/deps") + into("../common/src/commonMain/resources/libs/linux-x86_64") + include("*.so") + eachFile { + path = name + } + includeEmptyDirs = false + duplicatesStrategy = DuplicatesStrategy.INCLUDE + } + copy { + from("${project(":desktop").buildDir}/cmake/main/linux-aarch64", "$cppPath/desktop/libs/linux-aarch64", "$cppPath/desktop/libs/linux-aarch64/deps") + into("../common/src/commonMain/resources/libs/linux-aarch64") + include("*.so") + eachFile { + path = name + } + includeEmptyDirs = false + duplicatesStrategy = DuplicatesStrategy.INCLUDE + } + copy { + from("${project(":desktop").buildDir}/cmake/main/win-amd64", "$cppPath/desktop/libs/windows-x86_64", "$cppPath/desktop/libs/windows-x86_64/deps") + into("../common/src/commonMain/resources/libs/windows-x86_64") + include("*.dll") + eachFile { + path = name + } + includeEmptyDirs = false + duplicatesStrategy = DuplicatesStrategy.INCLUDE + } + copy { + from("${project(":desktop").buildDir}/cmake/main/mac-x86_64", "$cppPath/desktop/libs/mac-x86_64", "$cppPath/desktop/libs/mac-x86_64/deps") + into("../common/src/commonMain/resources/libs/mac-x86_64") + include("*.dylib") + eachFile { + path = name + } + includeEmptyDirs = false + duplicatesStrategy = DuplicatesStrategy.INCLUDE + } + copy { + from("${project(":desktop").buildDir}/cmake/main/mac-aarch64", "$cppPath/desktop/libs/mac-aarch64", "$cppPath/desktop/libs/mac-aarch64/deps") + into("../common/src/commonMain/resources/libs/mac-aarch64") + include("*.dylib") + eachFile { + path = name + } + includeEmptyDirs = false + duplicatesStrategy = DuplicatesStrategy.INCLUDE + } + } + } +} diff --git a/apps/multiplatform/gradle.properties b/apps/multiplatform/gradle.properties index cbbffa086..ac73c373a 100644 --- a/apps/multiplatform/gradle.properties +++ b/apps/multiplatform/gradle.properties @@ -23,3 +23,13 @@ kotlin.code.style=official android.nonTransitiveRClass=true # Automatically convert third-party libraries to use AndroidX android.enableJetifier=true +kotlin.mpp.androidSourceSetLayoutVersion=2 + +android.version_name=5.2-beta.0 +android.version_code=129 + +desktop.version_name=1.0 + +kotlin.version=1.8.20 +gradle.plugin.version=7.4.2 +compose.version=1.4.0 diff --git a/apps/multiplatform/gradle/wrapper/gradle-wrapper.properties b/apps/multiplatform/gradle/wrapper/gradle-wrapper.properties index 88ac00ff1..00c09d815 100644 --- a/apps/multiplatform/gradle/wrapper/gradle-wrapper.properties +++ b/apps/multiplatform/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Mon Feb 14 14:23:51 GMT 2022 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/apps/multiplatform/settings.gradle b/apps/multiplatform/settings.gradle deleted file mode 100644 index dc20a6dbd..000000000 --- a/apps/multiplatform/settings.gradle +++ /dev/null @@ -1,17 +0,0 @@ -pluginManagement { - repositories { - gradlePluginPortal() - google() - mavenCentral() - } -} -dependencyResolutionManagement { - repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) - repositories { - google() - mavenCentral() - maven { url 'https://jitpack.io' } - } -} -rootProject.name = "SimpleX" -include ':android' diff --git a/apps/multiplatform/settings.gradle.kts b/apps/multiplatform/settings.gradle.kts new file mode 100644 index 000000000..ba047edf1 --- /dev/null +++ b/apps/multiplatform/settings.gradle.kts @@ -0,0 +1,21 @@ +pluginManagement { + repositories { + google() + gradlePluginPortal() + mavenCentral() + maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") + } + + plugins { + kotlin("multiplatform").version(extra["kotlin.version"] as String) + kotlin("android").version(extra["kotlin.version"] as String) + id("com.android.application").version(extra["gradle.plugin.version"] as String) + id("com.android.library").version(extra["gradle.plugin.version"] as String) + id("org.jetbrains.compose").version(extra["compose.version"] as String) + id("org.jetbrains.kotlin.plugin.serialization").version(extra["kotlin.version"] as String) + } +} + +rootProject.name = "app" + +include(":android", ":desktop", ":common") diff --git a/scripts/android/build-android-bundle.sh b/scripts/android/build-android-bundle.sh index 3cc37a04c..554e64edf 100755 --- a/scripts/android/build-android-bundle.sh +++ b/scripts/android/build-android-bundle.sh @@ -15,13 +15,13 @@ git clone https://github.com/simplex-chat/simplex-chat "$tmp/simplex-chat" git -C "$tmp/simplex-chat" checkout "$commit" # Create missing folders -mkdir -p "$tmp/simplex-chat/apps/multiplatform/android/src/main/cpp/libs/arm64-v8a" +mkdir -p "$tmp/simplex-chat/apps/multiplatform/common/src/commonMain/cpp/android/libs/arm64-v8a" curl -sSf "$libsim" -o "$tmp/libsimplex.zip" -unzip -o "$tmp/libsimplex.zip" -d "$tmp/simplex-chat/apps/multiplatform/android/src/main/cpp/libs/arm64-v8a" +unzip -o "$tmp/libsimplex.zip" -d "$tmp/simplex-chat/apps/multiplatform/common/src/commonMain/cpp/android/libs/arm64-v8a" curl -sSf "$libsup" -o "$tmp/libsupport.zip" -unzip -o "$tmp/libsupport.zip" -d "$tmp/simplex-chat/apps/multiplatform/android/src/main/cpp/libs/arm64-v8a" +unzip -o "$tmp/libsupport.zip" -d "$tmp/simplex-chat/apps/multiplatform/common/src/commonMain/cpp/android/libs/arm64-v8a" gradle -p "$tmp/simplex-chat/apps/multiplatform/" clean build cp "$tmp/simplex-chat/apps/multiplatform/android/build/outputs/apk/release/android-release-unsigned.apk" "$PWD/simplex-chat.apk" diff --git a/scripts/android/build-android.sh b/scripts/android/build-android.sh index 8d5e3612b..90916a96f 100755 --- a/scripts/android/build-android.sh +++ b/scripts/android/build-android.sh @@ -82,7 +82,7 @@ checks() { build() { # Build preparations sed -i.bak 's/${extract_native_libs}/true/' "$folder/apps/multiplatform/android/src/main/AndroidManifest.xml" - sed -i.bak '/android {/a lint {abortOnError false}' "$folder/apps/multiplatform/android/build.gradle" + sed -i.bak '/android {/a lint {abortOnError false}' "$folder/apps/multiplatform/android/build.gradle.kts" for arch in $arches; do android_simplex_lib="${folder}#hydraJobs.${arch}-android:lib:simplex-chat.x86_64-linux" @@ -95,7 +95,7 @@ build() { android_tmp_folder="${tmp}/android-${arch}" android_apk_output="${folder}/apps/multiplatform/android/build/outputs/apk/release/android-${android_arch}-release-unsigned.apk" android_apk_output_final="simplex-chat-${android_arch}.apk" - libs_folder="$folder/apps/multiplatform/android/src/main/cpp/libs" + libs_folder="$folder/apps/multiplatform/common/src/commonMain/cpp/android/libs" # Create missing folders mkdir -p "$libs_folder/$android_arch" @@ -107,7 +107,7 @@ build() { unzip -o "$android_support_lib_output" -d "$libs_folder/$android_arch" # Build only one arch - sed -i.bak "s/include '.*/include '${android_arch}'/" "$folder/apps/multiplatform/android/build.gradle" + sed -i.bak "s/include '.*/include '${android_arch}'/" "$folder/apps/multiplatform/android/build.gradle.kts" gradle -p "$folder/apps/multiplatform/" clean assembleRelease mkdir -p "$android_tmp_folder" diff --git a/scripts/android/download-libs.sh b/scripts/android/download-libs.sh index c329206cd..f67cc397a 100755 --- a/scripts/android/download-libs.sh +++ b/scripts/android/download-libs.sh @@ -33,7 +33,7 @@ root_dir="$(dirname "$(dirname "$(readlink "$0")")")" for ((i = 0 ; i < ${#arches[@]}; i++)); do arch="${arches[$i]}" output_arch="${output_arches[$i]}" - output_dir="$root_dir/apps/multiplatform/android/src/main/cpp/libs/$output_arch/" + output_dir="$root_dir/apps/multiplatform/common/src/commonMain/cpp/android/libs/$output_arch/" mkdir -p "$output_dir" 2> /dev/null diff --git a/scripts/android/prepare.sh b/scripts/android/prepare.sh index e649ea77f..683d9cbf8 100755 --- a/scripts/android/prepare.sh +++ b/scripts/android/prepare.sh @@ -1,12 +1,12 @@ #!/bin/sh # libsimplex.so and libsupport.so binaries should be in ~/Downloads folder in their directories based on archive name -mkdir -p ./apps/multiplatform/android/src/main/cpp/libs/arm64-v8a/ -rm ./apps/multiplatform/android/src/main/cpp/libs/arm64-v8a/* -unzip -o ~/Downloads/pkg-aarch64-android-libsupport.zip -d ./apps/multiplatform/android/src/main/cpp/libs/arm64-v8a -unzip -o ~/Downloads/pkg-aarch64-android-libsimplex.zip -d ./apps/multiplatform/android/src/main/cpp/libs/arm64-v8a/ +mkdir -p ./apps/multiplatform/common/src/commonMain/cpp/android/libs/arm64-v8a/ +rm ./apps/multiplatform/common/src/commonMain/cpp/android/libs/arm64-v8a/* +unzip -o ~/Downloads/pkg-aarch64-android-libsupport.zip -d ./apps/multiplatform/common/src/commonMain/cpp/android/libs/arm64-v8a +unzip -o ~/Downloads/pkg-aarch64-android-libsimplex.zip -d ./apps/multiplatform/common/src/commonMain/cpp/android/libs/arm64-v8a/ -mkdir -p ./apps/multiplatform/android/src/main/cpp/libs/armeabi-v7a/ -rm ./apps/multiplatform/android/src/main/cpp/libs/armeabi-v7a/* -unzip -o ~/Downloads/pkg-armv7a-android-libsupport.zip -d ./apps/multiplatform/android/src/main/cpp/libs/armeabi-v7a/ -unzip -o ~/Downloads/pkg-armv7a-android-libsimplex.zip -d ./apps/multiplatform/android/src/main/cpp/libs/armeabi-v7a/ +mkdir -p ./apps/multiplatform/common/src/commonMain/cpp/android/libs/armeabi-v7a/ +rm ./apps/multiplatform/common/src/commonMain/cpp/android/libs/armeabi-v7a/* +unzip -o ~/Downloads/pkg-armv7a-android-libsupport.zip -d ./apps/multiplatform/common/src/commonMain/cpp/android/libs/armeabi-v7a/ +unzip -o ~/Downloads/pkg-armv7a-android-libsimplex.zip -d ./apps/multiplatform/common/src/commonMain/cpp/android/libs/armeabi-v7a/