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 80041efe40.

* EOLs

* change version to 1.0 to appease linter

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
This commit is contained in:
Stanislav Dmitrenko 2023-07-01 22:44:36 +03:00 committed by GitHub
parent 4c33ed92bb
commit 3bd5fc7463
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
33 changed files with 3042 additions and 347 deletions

View file

@ -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

View file

@ -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" }
}
}

View file

@ -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)
}
}
}
}

View file

@ -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 (

View file

@ -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())

View file

@ -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))

View file

@ -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<Placeable> = measureable.fastMap {
val placeables: List<Placeable> = measureable.map {
if (it.layoutId == priorityLayoutId)
imagePlaceable!!
else

View file

@ -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 })
}
}
}

View file

@ -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
}

View file

@ -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)
}

View file

@ -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"]}\"")
}
}

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="chat.simplex.common">
<uses-permission android:name="android.permission.VIBRATE" />
</manifest>

View file

@ -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})
${log-lib})

View file

@ -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}"
#)

File diff suppressed because it is too large Load diff

View file

@ -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_ */

View file

@ -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_ */

View file

@ -0,0 +1,98 @@
#include <jni.h>
// 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"), "<init>", "(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;
}

View file

@ -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")

View file

@ -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")

View file

@ -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")

View file

@ -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")

View file

@ -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")

View file

@ -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<com.github.tomtzook.gcmake.targets.TargetMachine>(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
}
}
}
}

View file

@ -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

View file

@ -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

View file

@ -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'

View file

@ -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")

View file

@ -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"

View file

@ -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"

View file

@ -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

View file

@ -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/