mirror of
https://github.com/Tencent/MMKV.git
synced 2026-10-16 20:21:12 +08:00
Merge pull request #1696 from Tencent/dev
Fix KMP IDE imports and sample builds
This commit is contained in:
+42
-1
@@ -150,7 +150,30 @@ duplicate native symbols.
|
||||
## Build from source
|
||||
|
||||
Building the KMP project and its iOS targets requires macOS, Xcode command-line
|
||||
tools, CMake, and JDK 11 or newer:
|
||||
tools, CMake, and JDK 21. The checked-in Gradle daemon JVM criteria select JDK 21
|
||||
for both command-line builds and Android Studio imports; install it before syncing.
|
||||
|
||||
If Android Studio cannot find `cmake` on its PATH, set `cmake.dir` to the CMake
|
||||
installation directory containing `bin/cmake` in the untracked
|
||||
`KMP/local.properties`. For example, with Homebrew on Apple Silicon:
|
||||
|
||||
```properties
|
||||
cmake.dir=/opt/homebrew
|
||||
```
|
||||
|
||||
Both native configure and build tasks use this path. When `cmake.dir` is unset,
|
||||
they use `cmake` from PATH.
|
||||
|
||||
Open the `KMP` directory in Android Studio. The sample is enabled by
|
||||
`MMKV_INCLUDE_SAMPLE=true` in `gradle.properties`. After syncing, select the
|
||||
Android App run configuration for `:sample:composeApp` to run the Android sample.
|
||||
Use `-PMMKV_INCLUDE_SAMPLE=false` for a library-only build.
|
||||
|
||||
The sample enables Android and iOS by default. Its desktop configuration is
|
||||
disabled because the MMKV wrapper does not yet provide a JVM target. The existing
|
||||
desktop scaffold is retained behind `-PMMKV_ENABLE_DESKTOP=true` for development;
|
||||
it still requires JVM support in the wrapper before it can build. Published-MMKV
|
||||
mode always disables desktop, even when this flag is set.
|
||||
|
||||
```bash
|
||||
cd KMP
|
||||
@@ -161,4 +184,22 @@ cd KMP
|
||||
`com.tencent:mmkv:2.4.3` Android artifact has been published only to Maven
|
||||
Local.
|
||||
|
||||
To prepare the iOS sample, install CocoaPods and run the following from `KMP`:
|
||||
|
||||
```bash
|
||||
./gradlew :sample:composeApp:podInstall -PMMKV_INCLUDE_SAMPLE=true
|
||||
open sample/iosApp/iosApp.xcworkspace
|
||||
```
|
||||
|
||||
This generates the Pods support files, including the `.xcconfig` files referenced
|
||||
by the Xcode project. Use the generated workspace for Xcode builds. The sample is
|
||||
included automatically when Xcode invokes Gradle through the CocoaPods build script.
|
||||
|
||||
When running the iOS sample from Android Studio, its linked Xcode project must
|
||||
use `sample/iosApp/iosApp.xcworkspace` as well. If the IDE linked the `.xcodeproj`
|
||||
before `podInstall` created the workspace, invoke **Unlink Xcode project** via
|
||||
**Find Action**, then **Sync Project with Gradle Files** to detect the workspace.
|
||||
Building the standalone project omits the Pods target and can fail with
|
||||
`Framework 'Pods_iosApp' not found`.
|
||||
|
||||
Release maintainers should also follow [PUBLISHING.md](./PUBLISHING.md).
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
# Project-wide Gradle settings.
|
||||
org.gradle.jvmargs=-Xmx2048m
|
||||
|
||||
# Include the sample application in Android Studio imports.
|
||||
MMKV_INCLUDE_SAMPLE=true
|
||||
|
||||
# Android
|
||||
android.useAndroidX=true
|
||||
android.nonTransitiveRClass=false
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
# Keep the build JVM compatible with Gradle 8.14, including Android Studio imports.
|
||||
toolchainVersion=21
|
||||
@@ -18,6 +18,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import java.util.Properties
|
||||
import org.gradle.api.publish.maven.MavenPublication
|
||||
import org.gradle.api.tasks.Exec
|
||||
import org.gradle.api.tasks.bundling.Jar
|
||||
@@ -71,6 +72,19 @@ version = publishVersion
|
||||
val nativeInteropDir = project.file("nativeInterop")
|
||||
val nativeBuildRoot = nativeInteropDir.resolve("build")
|
||||
|
||||
// These custom Exec tasks do not use AGP's CMake discovery. Honor cmake.dir so
|
||||
// IDE imports do not depend on the GUI process inheriting the shell's PATH.
|
||||
val localProperties = Properties().apply {
|
||||
val propertiesFile = rootProject.file("local.properties")
|
||||
if (propertiesFile.isFile) {
|
||||
propertiesFile.inputStream().use { load(it) }
|
||||
}
|
||||
}
|
||||
val cmakeExecutable = localProperties.getProperty("cmake.dir")
|
||||
?.trim()?.takeIf { it.isNotEmpty() }
|
||||
?.let { rootProject.file(it).resolve("bin/cmake").absolutePath }
|
||||
?: "cmake"
|
||||
|
||||
fun taskSuffix(label: String): String =
|
||||
label.split('-', '_')
|
||||
.filter { it.isNotBlank() }
|
||||
@@ -90,6 +104,7 @@ fun registerCMakeBuildTask(
|
||||
|
||||
inputs.file(nativeInteropDir.resolve("CMakeLists.txt"))
|
||||
inputs.file(nativeInteropDir.resolve("cinterop/mmkv.def"))
|
||||
inputs.property("cmakeExecutable", cmakeExecutable)
|
||||
outputs.file(buildDir.resolve("CMakeCache.txt"))
|
||||
outputs.file(buildDir.resolve("include/MMKVBridge.h"))
|
||||
|
||||
@@ -98,7 +113,7 @@ fun registerCMakeBuildTask(
|
||||
workingDir = nativeInteropDir
|
||||
commandLine(
|
||||
buildList {
|
||||
add("cmake")
|
||||
add(cmakeExecutable)
|
||||
add("-S")
|
||||
add(".")
|
||||
add("-B")
|
||||
@@ -126,6 +141,7 @@ fun registerCMakeBuildTask(
|
||||
|
||||
inputs.file(nativeInteropDir.resolve("CMakeLists.txt"))
|
||||
inputs.file(nativeInteropDir.resolve("cinterop/mmkv.def"))
|
||||
inputs.property("cmakeExecutable", cmakeExecutable)
|
||||
outputs.file(buildDir.resolve("libmmkv-kmp.a"))
|
||||
// Let CMake perform its own incremental source check. Gradle cannot
|
||||
// reliably model FetchContent/local Core source inputs here.
|
||||
@@ -134,7 +150,7 @@ fun registerCMakeBuildTask(
|
||||
workingDir = nativeInteropDir
|
||||
commandLine(
|
||||
buildList {
|
||||
add("cmake")
|
||||
add(cmakeExecutable)
|
||||
add("--build")
|
||||
add(buildDir.absolutePath)
|
||||
add("--config")
|
||||
|
||||
@@ -7,6 +7,10 @@ plugins {
|
||||
}
|
||||
|
||||
val usePublishedMMKV = providers.gradleProperty("MMKV_USE_PUBLISHED").orNull == "true"
|
||||
// The MMKV wrapper currently has no JVM target. Keep the desktop scaffold
|
||||
// opt-in so normal imports and aggregate builds only use supported targets.
|
||||
val enableDesktop = !usePublishedMMKV &&
|
||||
providers.gradleProperty("MMKV_ENABLE_DESKTOP").orNull == "true"
|
||||
val mmkvVersion = providers.gradleProperty("VERSION_NAME").getOrElse("2.4.3")
|
||||
|
||||
kotlin {
|
||||
@@ -16,8 +20,7 @@ kotlin {
|
||||
}
|
||||
}
|
||||
|
||||
if (!usePublishedMMKV) {
|
||||
// Desktop is available only when the sample consumes the in-tree project.
|
||||
if (enableDesktop) {
|
||||
jvm("desktop") {
|
||||
compilerOptions {
|
||||
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11)
|
||||
@@ -61,7 +64,7 @@ kotlin {
|
||||
implementation("androidx.activity:activity-compose:1.10.1")
|
||||
}
|
||||
}
|
||||
if (!usePublishedMMKV) {
|
||||
if (enableDesktop) {
|
||||
val desktopMain by getting {
|
||||
dependencies {
|
||||
implementation(compose.desktop.currentOs)
|
||||
@@ -71,7 +74,7 @@ kotlin {
|
||||
}
|
||||
}
|
||||
|
||||
if (!usePublishedMMKV) {
|
||||
if (enableDesktop) {
|
||||
compose.desktop {
|
||||
application {
|
||||
mainClass = "com.tencent.mmkv.sample.MainKt"
|
||||
|
||||
@@ -26,6 +26,9 @@ dependencyResolutionManagement {
|
||||
}
|
||||
|
||||
include(":mmkv")
|
||||
if (providers.gradleProperty("MMKV_INCLUDE_SAMPLE").orNull == "true") {
|
||||
// Xcode's generated CocoaPods script passes platform/arch/configuration, but
|
||||
// does not forward the MMKV_INCLUDE_SAMPLE flag used during pod installation.
|
||||
val isCocoaPodsBuild = providers.gradleProperty("kotlin.native.cocoapods.platform").isPresent
|
||||
if (providers.gradleProperty("MMKV_INCLUDE_SAMPLE").orNull == "true" || isCocoaPodsBuild) {
|
||||
include(":sample:composeApp")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user