Skip to content

Commit

Permalink
Optimize binary size for Android and iOS build
Browse files Browse the repository at this point in the history
Signed-off-by: kexuan.yang <kexuan.yang@gmail.com>
  • Loading branch information
yangkx1024 committed Apr 29, 2024
1 parent 85dd5d6 commit d4b8c4a
Show file tree
Hide file tree
Showing 17 changed files with 151 additions and 136 deletions.
9 changes: 9 additions & 0 deletions .cargo/config.toml
@@ -0,0 +1,9 @@
[build]
#target = "x86_64-linux-android"

[target.'cfg(any(target_os="android", target_os="ios"))']
[profile.release]
opt-level = 'z'
lto = true
codegen-units = 1
panic = 'abort'
1 change: 0 additions & 1 deletion .gitignore
Expand Up @@ -4,7 +4,6 @@
.DS_Store
mini_mmkv
mini_mmkv.meta
.cargo
.swiftpm
.build
.vscode
140 changes: 77 additions & 63 deletions README.md
Expand Up @@ -12,7 +12,8 @@ This is a Rust version of [MMKV](https://github.com/Tencent/MMKV).

By default, this lib uses [CRC8](https://github.com/mrhooray/crc-rs) to check data integrity.

If include feature `encryption`, this lib will encrypt the data with [AES-EAX](https://github.com/RustCrypto/AEADs/tree/master/eax).
If include feature `encryption`, this lib will encrypt the data
with [AES-EAX](https://github.com/RustCrypto/AEADs/tree/master/eax).

MMKV is thread-safe but cannot guarantee cross-process data consistency.
If you want to use it in a cross-process scenario, please ensure that there is no competing write.
Expand All @@ -26,28 +27,36 @@ Add dependency:
And use `MMKV` directly:

```rust
use mmkv::MMKV;
use mmkv::{LogLevel, MMKV};

fn main() {
// initialize it with a directory,
// the library will crate a file,
// named "mini_mmkv" under this dir
MMKV::initialize(".");
MMKV::put_i32("key1", 1);
// Ok(1)
println!("{:?}", MMKV::get_i32("key1"));
MMKV::put_str("key1", "value");
// Err(Error::KeyNotFound), cause "key1" was override by put_str
println!("{:?}", MMKV::get_i32("key1"));
// Ok("value")
println!("{:?}", MMKV::get_str("key1"));
MMKV::put_bool("key1", true);
// Ok(true)
println!("{:?}", MMKV::get_bool("key1"));
// close the instance if you need to re-initialize with different config.
// MMKV::close();
// clear all related data to free disk space, this call will also close the instance.
// MMKV::clear_data();
// Set the log level of the library
MMKV::set_log_level(LogLevel::Verbose);
let temp_dir = std::env::temp_dir();
let dir = temp_dir.join("test1");
let _ = std::fs::create_dir(&dir);
// Initialize it with a directory, the library will crate a file,
// named "mini_mmkv" under this dir.
let mmkv = MMKV::new(dir.to_str().unwrap());
// Put and get result, for most case should be Ok(()),
// if something wrong, it contains the useful info.
let ret = mmkv.put_i32("key1", 1);
println!("{:?}", ret); // Ok(())
// Get result with key
println!("{:?}", mmkv.get_i32("key1")); // Ok(1)
// Put and unwrap the result
mmkv.put_str("key1", "value").unwrap();
println!("{:?}", mmkv.get_i32("key1")); // Err(TypeMissMatch)
println!("{:?}", mmkv.get_str("key1")); // Ok("value")

let dir = temp_dir.join("test2");
let _ = std::fs::create_dir(&dir);
// Create another instance with different path
let new_mmkv = MMKV::new(dir.to_str().unwrap());
new_mmkv.put_bool("key1", true).unwrap();
println!("{:?}", new_mmkv.get_bool("key1")); // Ok(true)
// clear all data to free disk space
new_mmkv.clear_data();
}
```

Expand All @@ -59,9 +68,10 @@ Add dependency:

Then init `MMKV` with an encryption credential:

`MMKV::initialize(".", "88C51C536176AD8A8EE4A06F62EE897E")`
`let mmkv = MMKV::new(".", "88C51C536176AD8A8EE4A06F62EE897E")`

Encryption will greatly reduce the efficiency of reading and writing, and will also increase the file size, use at your own risk!
Encryption will greatly reduce the efficiency of reading and writing, and will also increase the file size, use at your
own risk!

## Use in Android projects

Expand All @@ -81,26 +91,36 @@ Use the kotlin API:

```kotlin
class MyApplication : Application() {

companion object {
lateinit var mmkv: MMKV
}

override fun onCreate() {
super.onCreate()
MMKV.setLogLevel(LogLevel.VERBOSE)
val dir = this.getDir("mmkv", Context.MODE_PRIVATE)
MMKV.initialize(dir.absolutePath)
mmkv = MMKV(dir.absolutePath)
// If you are using mmkv with encryption
// MMKV.initialize(dir.absolutePath, "88C51C536176AD8A8EE4A06F62EE897E")
// mmkv = MMKV(dir.absolutePath, "88C51C536176AD8A8EE4A06F62EE897E")
}
}

class MainActivity : AppCompatActivity() {

private val mmkv: MMKV
get() = MyApplication.mmkv

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
MMKV.putString("first_key", "first value")
MMKV.putInt("second_key", 1024)
MMKV.putBool("third_key", true)
binding.string.text = MMKV.getString("first_key", "default")
binding.integer.text = MMKV.getInt("second_key", 0).toString()
binding.bool.text = MMKV.getBool("third_key", false).toString()
mmkv.putString("first_key", "first value")
mmkv.putInt("second_key", 1024)
mmkv.putBool("third_key", true)
binding.string.text = mmkv.getString("first_key", "default")
binding.integer.text = mmkv.getInt("second_key", 0).toString()
binding.bool.text = mmkv.getBool("third_key", false).toString()
}
}
```
Expand All @@ -113,35 +133,29 @@ Check the [android](https://github.com/yangkx1024/MMKV/tree/main/android) demo f

2. Init MMKV instance before use the API, for example:

```swift
import SwiftUI
import MMKV

@main
struct MMKVDemoApp: App {
init() {
initMMKV()
}
var body: some Scene {
...
}
}

func initMMKV() {
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let documentsDirectory = paths[0]
let docURL = URL(string: documentsDirectory)!
let dataPath = docURL.appendingPathComponent("mmkv")
if !FileManager.default.fileExists(atPath: dataPath.path) {
do {
try FileManager.default.createDirectory(atPath: dataPath.path, withIntermediateDirectories: true, attributes: nil)
} catch {
print(error.localizedDescription)
}
}
MMKV.shared.initialize(dir: dataPath.path)
}
```
```swift
import Foundation
import MMKV

class MMKVManager {
static var inst = initMMKV()
}

func initMMKV() -> MMKV {
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let documentsDirectory = paths[0]
let docURL = URL(string: documentsDirectory)!
let dataPath = docURL.appendingPathComponent("mmkv")
if !FileManager.default.fileExists(atPath: dataPath.path) {
do {
try FileManager.default.createDirectory(atPath: dataPath.path, withIntermediateDirectories: true, attributes: nil)
} catch {
print(error.localizedDescription)
}
}
return MMKV(dataPath.path)
}
```

3. Use `MMKV.shared` to access API directly:

Expand All @@ -154,9 +168,9 @@ Check the [android](https://github.com/yangkx1024/MMKV/tree/main/android) demo f
var body: some View {
Text(textContent)
.onTapGesture {
let value = MMKV.shared.getInt32(key: "int_key").unwrap(defalutValue: 0)
MMKV.shared.putInt32(key: "int_key", value: value + 1).unwrap(defalutValue: ())
textContent = MMKV.shared.getInt32(key: "int_key").unwrap(defalutValue: 0).formatted()
let value = MMKVManager.inst.getInt32(key: "int_key").unwrap(defalutValue: 0)
MMKVManager.inst.putInt32(key: "int_key", value: value + 1).unwrap(defalutValue: ())
textContent = MMKVManager.inst.getInt32(key: "int_key").unwrap(defalutValue: 0).formatted()
}
}
}
Expand Down
Binary file modified android/library-encrypt/src/main/jniLibs/arm64-v8a/libmmkv.so
Binary file not shown.
Binary file modified android/library-encrypt/src/main/jniLibs/armeabi-v7a/libmmkv.so
Binary file not shown.
Binary file modified android/library-encrypt/src/main/jniLibs/x86_64/libmmkv.so
Binary file not shown.
Binary file modified android/library/src/main/jniLibs/arm64-v8a/libmmkv.so
Binary file not shown.
Binary file modified android/library/src/main/jniLibs/armeabi-v7a/libmmkv.so
Binary file not shown.
Binary file modified android/library/src/main/jniLibs/x86_64/libmmkv.so
Binary file not shown.
2 changes: 2 additions & 0 deletions build_android.sh
Expand Up @@ -29,8 +29,10 @@ for ITEM in "${targets_dic[@]}" ; do
rustup target add "$TARGET"
echo "Building with default feature......"
cargo build --target "$TARGET" --release
"$ANDROID_NDK_TOOLCHAINS_PATH"/llvm-strip target/"$TARGET"/release/libmmkv.so
cp target/"$TARGET"/release/libmmkv.so android/library/src/main/jniLibs/"$ANDROID_TARGET"/libmmkv.so
echo "Building with feature encryption...."
cargo build --features encryption --target "$TARGET" --release
"$ANDROID_NDK_TOOLCHAINS_PATH"/llvm-strip target/"$TARGET"/release/libmmkv.so
cp target/"$TARGET"/release/libmmkv.so android/library-encrypt/src/main/jniLibs/"$ANDROID_TARGET"/libmmkv.so
done
1 change: 1 addition & 0 deletions build_apple.sh
Expand Up @@ -10,6 +10,7 @@ do
echo "Build for $TARGET..."
rustup target add $TARGET
cargo build -r --target=$TARGET
strip target/"$TARGET"/release/libmmkv.a
done

HEADER="include"
Expand Down
Binary file modified ios/MMKV/RustMMKV.xcframework.zip
Binary file not shown.
4 changes: 4 additions & 0 deletions ios/MMKVDemo/MMKVDemo.xcodeproj/project.pbxproj
Expand Up @@ -13,6 +13,7 @@
2B237B5F2AFBC69B006CA835 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2B237B5E2AFBC69B006CA835 /* Preview Assets.xcassets */; };
2B2DF9AC2B2DF314002D1AEE /* MMKV in Frameworks */ = {isa = PBXBuildFile; productRef = 2B2DF9AB2B2DF314002D1AEE /* MMKV */; };
2BB59D092B049877006ED8BF /* LogView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BB59D082B049877006ED8BF /* LogView.swift */; };
A12C90482BDFC88900AE6E98 /* MMKVManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A12C90472BDFC88900AE6E98 /* MMKVManager.swift */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
Expand All @@ -23,6 +24,7 @@
2B237B5E2AFBC69B006CA835 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
2B2DF9AA2B2DF308002D1AEE /* mmkv */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = mmkv; path = ../..; sourceTree = "<group>"; };
2BB59D082B049877006ED8BF /* LogView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogView.swift; sourceTree = "<group>"; };
A12C90472BDFC88900AE6E98 /* MMKVManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MMKVManager.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -62,6 +64,7 @@
2BB59D082B049877006ED8BF /* LogView.swift */,
2B237B5B2AFBC69B006CA835 /* Assets.xcassets */,
2B237B5D2AFBC69B006CA835 /* Preview Content */,
A12C90472BDFC88900AE6E98 /* MMKVManager.swift */,
);
path = MMKVDemo;
sourceTree = "<group>";
Expand Down Expand Up @@ -159,6 +162,7 @@
files = (
2B237B5A2AFBC699006CA835 /* ContentView.swift in Sources */,
2BB59D092B049877006ED8BF /* LogView.swift in Sources */,
A12C90482BDFC88900AE6E98 /* MMKVManager.swift in Sources */,
2B237B582AFBC699006CA835 /* MMKVDemoApp.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
73 changes: 35 additions & 38 deletions ios/MMKVDemo/MMKVDemo/ContentView.swift
Expand Up @@ -3,73 +3,70 @@ import MMKV

struct ContentView: View {

@State var logger = CustomLogger(LogLevel.trace, "")
var body: some View {
VStack(spacing: 10) {
MMVKView(content: "String value") { key in
let value = MMKVManager.mmkv.getString(key).unwrap("")
MMKVManager.mmkv.putString(key, value + "1").unwrap(())
return MMKVManager.mmkv.getString(key).unwrap("")
let value = MMKVManager.inst.getString(key).unwrap("")
MMKVManager.inst.putString(key, value + "1").unwrap(())
return MMKVManager.inst.getString(key).unwrap("")
}
MMVKView(content: "Bool value") { key in
let value = MMKVManager.mmkv.getBool(key).unwrap(false)
MMKVManager.mmkv.putBool(key, !value).unwrap(())
return MMKVManager.mmkv.getBool(key).unwrap(false).description
let value = MMKVManager.inst.getBool(key).unwrap(false)
MMKVManager.inst.putBool(key, !value).unwrap(())
return MMKVManager.inst.getBool(key).unwrap(false).description
}
MMVKView(content: "Int32 value") { key in
let value = MMKVManager.mmkv.getInt32(key).unwrap(0)
MMKVManager.mmkv.putInt32(key, value + 1).unwrap(())
return MMKVManager.mmkv.getInt32(key).unwrap(0).description
let value = MMKVManager.inst.getInt32(key).unwrap(0)
MMKVManager.inst.putInt32(key, value + 1).unwrap(())
return MMKVManager.inst.getInt32(key).unwrap(0).description
}
MMVKView(content: "Int64 value") { key in
let value = MMKVManager.mmkv.getInt64(key).unwrap(0)
MMKVManager.mmkv.putInt64(key, value + 1).unwrap(())
return MMKVManager.mmkv.getInt64(key).unwrap(0).description
let value = MMKVManager.inst.getInt64(key).unwrap(0)
MMKVManager.inst.putInt64(key, value + 1).unwrap(())
return MMKVManager.inst.getInt64(key).unwrap(0).description
}
MMVKView(content: "Float32 value") { key in
let value = MMKVManager.mmkv.getFloat32(key).unwrap(0.1)
MMKVManager.mmkv.putFloat32(key, value + 1).unwrap(())
return MMKVManager.mmkv.getFloat32(key).unwrap(0).description
let value = MMKVManager.inst.getFloat32(key).unwrap(0.1)
MMKVManager.inst.putFloat32(key, value + 1).unwrap(())
return MMKVManager.inst.getFloat32(key).unwrap(0).description
}
MMVKView(content: "Float64 value") { key in
let value = MMKVManager.mmkv.getFloat64(key).unwrap(0.1)
MMKVManager.mmkv.putFloat64(key, value + 1).unwrap(())
return MMKVManager.mmkv.getFloat64(key).unwrap(0).description
let value = MMKVManager.inst.getFloat64(key).unwrap(0.1)
MMKVManager.inst.putFloat64(key, value + 1).unwrap(())
return MMKVManager.inst.getFloat64(key).unwrap(0).description
}
MMVKView(content: "Byte array value") { key in
let _ = MMKVManager.mmkv.getByteArray(key).unwrap([])
MMKVManager.mmkv.putByteArray(key,[UInt8.random(in: 0...100), UInt8.random(in: 0...100), UInt8.random(in: 0...100)]).unwrap(())
return MMKVManager.mmkv.getByteArray(key).unwrap([]).description
let _ = MMKVManager.inst.getByteArray(key).unwrap([])
MMKVManager.inst.putByteArray(key,[UInt8.random(in: 0...100), UInt8.random(in: 0...100), UInt8.random(in: 0...100)]).unwrap(())
return MMKVManager.inst.getByteArray(key).unwrap([]).description
}
MMVKView(content: "Int32 array value") { key in
let _ = MMKVManager.mmkv.getInt32Array(key).unwrap([])
MMKVManager.mmkv.putInt32Array(key, [Int32.random(in: 0...100), Int32.random(in: 0...100), Int32.random(in: 0...100)]).unwrap(())
return MMKVManager.mmkv.getInt32Array(key).unwrap([]).description
let _ = MMKVManager.inst.getInt32Array(key).unwrap([])
MMKVManager.inst.putInt32Array(key, [Int32.random(in: 0...100), Int32.random(in: 0...100), Int32.random(in: 0...100)]).unwrap(())
return MMKVManager.inst.getInt32Array(key).unwrap([]).description
}
MMVKView(content: "Int64 array value") { key in
let _ = MMKVManager.mmkv.getInt64Array(key).unwrap([])
MMKVManager.mmkv.putInt64Array(key, [Int64.random(in: 0...100), Int64.random(in: 0...100), Int64.random(in: 0...100)]).unwrap(())
return MMKVManager.mmkv.getInt64Array(key).unwrap([]).description
let _ = MMKVManager.inst.getInt64Array(key).unwrap([])
MMKVManager.inst.putInt64Array(key, [Int64.random(in: 0...100), Int64.random(in: 0...100), Int64.random(in: 0...100)]).unwrap(())
return MMKVManager.inst.getInt64Array(key).unwrap([]).description
}
MMVKView(content: "Float32 array value") { key in
let _ = MMKVManager.mmkv.getFloat32Array(key).unwrap([])
MMKVManager.mmkv.putFloat32Array(key, [Float32.random(in: 0...100), Float32.random(in: 0...100), Float32.random(in: 0...100)]).unwrap(())
return MMKVManager.mmkv.getFloat32Array(key).unwrap([]).description
let _ = MMKVManager.inst.getFloat32Array(key).unwrap([])
MMKVManager.inst.putFloat32Array(key, [Float32.random(in: 0...100), Float32.random(in: 0...100), Float32.random(in: 0...100)]).unwrap(())
return MMKVManager.inst.getFloat32Array(key).unwrap([]).description
}
MMVKView(content: "Float64 array value") { key in
let _ = MMKVManager.mmkv.getFloat64Array(key).unwrap([])
MMKVManager.mmkv.putFloat64Array(key, [Float64.random(in: 0...100), Float64.random(in: 0...100), Float64.random(in: 0...100)]).unwrap(())
return MMKVManager.mmkv.getFloat64Array(key).unwrap([]).description
let _ = MMKVManager.inst.getFloat64Array(key).unwrap([])
MMKVManager.inst.putFloat64Array(key, [Float64.random(in: 0...100), Float64.random(in: 0...100), Float64.random(in: 0...100)]).unwrap(())
return MMKVManager.inst.getFloat64Array(key).unwrap([]).description
}
Spacer()
Button(action: {
MMKVManager.mmkv.clearData()
MMKVManager.reInit()
logger = CustomLogger(LogLevel.debug, "MMKV log:")
MMKVManager.inst.clearData()
}, label: {
Text("Clear Data")
})
LogView(logger)
LogView(CustomLogger(LogLevel.debug, "MMKV log:"))
}
}
}
Expand Down

0 comments on commit d4b8c4a

Please sign in to comment.