logo
hero image

Sharing Code iOS & Android dengan Rust

Tutorial memanggil kode Rust di Swift dan Kotlin menggunakan UniFFI.
25 August 2024 · 8 Minutes

Dalam membuat aplikasi Mobile tentu menggunakan teknologi Native dari masing-masing platform seperti SwiftUI untuk iOS dan Jetpack Compose untuk Android adalah pilihan terbaik dalam segi performa dan User Experience (UX).

Namun, kita juga tahu bahwa dalam membangun aplikasi Mobile, kita tidak hanya membuat User Interface (UI) saja, ada banyak sekali hal lain yang perlu kita buat, seperti network call, caching, image processing, dll. Yang mana itu sebetulnya tidak platform specific seperti UI, sehingga kita bisa mengurangi redundansi penulisan kode untuk bagian-bagian tersebut dengan cara hanya menulis 1 kali saja, kemudian kita akan pakai di kedua platform!

Ada beberapa cara Sharing Code yang bisa kita pilih, mungkin menggunakan Kotlin Multi Platform (KMP), mungkin menggunakan C++, atau menggunakan bahasa pemrograman Rust yang akan kita gunakan dalam tutorial ini.

Kenapa Rust?

Berikut adalah beberapa alasan mengapa Rust mungkin cocok digunakan dalam Sharing Code pada aplikasi Mobile:

1. Performance

Rust dikenal sebagai bahasa yang memiliki performa sangat tinggi, bahkan bisa mendekati C/C++. Hal ini bisa didapatkan dari Zero-Cost Abstraction (abstraksi yang tidak berdampak ke performa pada runtime) yang ada pada Rust dan juga memory management yang tidak menggunakan Garbage Collector.

Karena performanya yang sangat oke, ada beberapa perusahaan besar yang mulai mengadopsi Rust, contohnya seperti Discord (dari Go ke Rust), Figma (dari Typescript ke Rust), dll

2. Memory Safety

Memory Safety artinya program kita akan terbebas dari bugs yang berhubungan dengan memory management, seperti memory leaks (memory tidak pernah di-deallocate), mengakses null pointer, melakukan double free, dll.

Nah, di Rust, masalah-masalah tersebut akan terdeteksi lebih awal pada saat program kita dicompile.

Karena alasan memory safety inilah Linux & Windows mulai mengadopsi Rust dalam kernel OS-nya. Bahkan departemen pertahanan AS (DARPA) mulai rewrite program yang mereka tulis menggunakan C ke Rust.

3. Productivity

Ada beberapa fitur pada Rust yang dapat meningkatkan produktivitas kita sebagai Developer, misalnya Macros untuk code generator, Auto Completion, Auto Formatter, dll.

Jika program kita ada error, error message nya pun sangat useful. bahkan kadang compilernya memberikan suggestion untuk memperbaiki error tersebut.

Selain itu, ada ratusan ribu crates (library) di crates.io yang dapat kita gunakan sehingga proses development menjadi lebih cepat.

4. Support dari Android

Sejak beberapa tahun lalu, Android sudah mendukung Rust sebagai bahasa pemrograman untuk membangun native OS components mereka. (https://source.android.com/docs/setup/build/rust/building-rust-modules/overview)

Prerequisites

Untuk mengikuti tutorial ini, pastikan kamu sudah menginstall:

  • Rust

  • Xcode

  • Android Studio

Setup Project

Sekarang, kita akan mulai membuat projectnya, kita akan membuat library Rust yang memiliki function get_message dan library tersebut akan kita gunakan di iOS dan Android.

Silakan buat folder baru bernama "greeting-demo"

1mkdir greeting-demo
2cd greeting-demo

Membuat Library Rust

Untuk membuat library Rust, jalankan command:

1cargo new greeting --lib

Kemudian tambahkan crate uniffi ke library kita:

Cargo.toml
1[lib]
2crate_type = ["cdylib", "staticlib"]
3name = "greeting"
4
5[dependencies]
6uniffi = { version = "0.28.1", features = ["cli"] }

Setelah itu tambahkan function get_message pada file "lib.rs":

lib.rs
icon
1uniffi::setup_scaffolding!();
2
3#[uniffi::export]
4fn get_message() -> String {
5 String::from("Hello from Rust! 🦀")
6}

Terakhir, buat file "uniffi-bindgen.rs" di dalam folder "bin", yang berisi:

uniffi-bindgen.rs
icon
1fn main() {
2 uniffi::uniffi_bindgen_main()
3}

Jika kita build, maka akan muncul sebuah dynamic library bernama "libgreeting.dylib" pada folder "target/debug" yang akan kita pakai pada step berikutnya.

1cargo build

Membuat Aplikasi iOS

1. Setup Project

Silakan buka Xcode dan buat project SwiftUI baru bernama "GreetingIOS" pada folder "greeting".

Setup ProjectSetup Project

2. Membuat iOS Binding & Binaries

Pertama, kita akan generate binding terlebih dahulu agar kita bisa memanggil library rust di swift.

1cargo run --bin uniffi-bindgen generate --library ./target/debug/libgreeting.dylib --language swift --out-dir ./bindings

Command di atas akan menghasilkan folder "bindings" di project rust kita yang berisi binding rust untuk swift.

Lalu pindahkan file "greeting.swift" ke folder "ios" dan rename menjadi "Greeting.swift"

1mv ./bindings/greeting.swift ./ios/Greeting.swift

Kemudian tambahkan beberapa target berikut ke Rust:

1rustup target add aarch64-apple-ios-sim aarch64-apple-ios

Jalankan command berikut untuk build library iOS:

1cargo build --release --target=aarch64-apple-ios-sim
2cargo build --release --target=aarch64-apple-ios

Command di atas akan menghasilkan 2 file binary bernama "target/aarch64-apple-ios-sim/release/libgreeting.a" dan "target/aarch64-apple-ios/release/libgreeting.a".

3. Membuat XCFramework

XCFramework memungkinkan kita untuk mengimport library iOS dengan lebih mudah. Jadi, kita akan membuat file .xcframework dari 2 file binary di atas.

Pertama, kita ubah rename dulu "bindings/greetingFFI.modulemap" menjadi "bindings/module.modulemap" agar Xcode dapat menemukan module kita.

Kemudian, buat file .xcframework:

1xcodebuild -create-xcframework \
2 -library ./target/aarch64-apple-ios-sim/release/libgreeting.a -headers ./bindings \
3 -library ./target/aarch64-apple-ios/release/libgreeting.a -headers ./bindings \
4 -output "ios/Greeting.xcframework"

4. Import XCFramework di Xcode

Silakan drag & drop file "Greeting.xcframework" dan file "Greeting.swift" ke project iOS kita.

Sekarang, kita sudah bisa memanggil function getMessage dari Rust di Swift.

Penamaan function akan disesuaikan secara otomatis sesuai konvensi dari masing-masing bahasa oleh binding yang telah kita buat di awal. Misalnya dalam hal ini get_message di Rust akan menjadi getMessage di Swift.

ContentView.swift
icon
1import SwiftUI
2
3struct ContentView: View {
4 var body: some View {
5 VStack {
7 Text(getMessage())
8 }
9 .padding()
10 }
11}
12
13#Preview {
14 ContentView()
15}

iOSiOS

5. Automation Script

Agar tiap kali ada perubahan di library Rust-nya kita tidak perlu menjalankan command satu per-satu, lebih baik kita membuat script automasi untuk pembuatan XCFramework.

Buat file baru bernama "build_ios.sh" yang berisi:

build ios.sh
1#!/bin/bash
2
3# Build the dylib
4cargo build
5
6# Generate bindings
7cargo run --bin uniffi-bindgen generate --library ./target/debug/libgreeting.dylib --language swift --out-dir ./bindings
8
9# Add the iOS targets and build
10for TARGET in \
11 aarch64-apple-darwin \
12 aarch64-apple-ios \
13 aarch64-apple-ios-sim \
14 x86_64-apple-darwin \
15 x86_64-apple-ios; do
16 rustup target add $TARGET
17 cargo build --release --target=$TARGET
18done
19
20# Rename *.modulemap to module.modulemap
21mv ./bindings/greetingFFI.modulemap ./bindings/module.modulemap
22
23# Move the Swift file to the project
24rm ./ios/Greeting.swift
25mv ./bindings/greeting.swift ./ios/Greeting.swift
26
27# Recreate XCFramework
28rm -rf "ios/Greeting.xcframework"
29xcodebuild -create-xcframework \
30 -library ./target/aarch64-apple-ios-sim/release/libgreeting.a -headers ./bindings \
31 -library ./target/aarch64-apple-ios/release/libgreeting.a -headers ./bindings \
32 -output "ios/Greeting.xcframework"
33
34# Cleanup
35rm -rf bindings
1chmod +x build_ios.sh
2./build_ios.sh

Membuat Aplikasi Android

1. Setup Project

Silakan buka Android Studio, dan buat project baru bernama "GreetingAndroid"

Setup ProjectSetup Project

Di Android, kita membutuhkan NDK (Native Development Kit) untuk menggunakan library yang ditulis menggunakan bahasa native seperti C, C++ dan Rust.

Silakan klik Tools -> SDK Manager -> SDK Tools kemudian "Check (NDK Side by Side)"

NDKNDK

Setelah itu pindah ke project Rust, dan jalankan command berikut:

1cargo install cargo-ndk

Dan tambahkan beberapa target berikut ke Rust:

1rustup target add \
2 aarch64-linux-android \
3 armv7-linux-androideabi \
4 i686-linux-android \
5 x86_64-linux-android

2. Membuat Library Android

Jalankan command berikut untuk membuat library Android:

1cargo ndk -o ../GreetingAndroid/app/src/main/jniLibs \
2 --manifest-path ./Cargo.toml \
3 -t armeabi-v7a \
4 -t arm64-v8a \
5 -t x86 \
6 -t x86_64 \
7 build --release

3. Generate Binding

Kemudian kita perlu generate Binding Rust ke Kotlin menggunakan command berikut:

1cargo run --bin uniffi-bindgen generate --library ./target/debug/libgreeting.dylib --language kotlin --out-dir ../GreetingAndroid/app/src/main/java/dev/alfin/greetingandroid

4. Import Library di Android Studio

Pertama, kita perlu menambahkan 2 dependencies berikut di file "build.gradle.kts"

1dependencies {
2 // ...
3 // UniFFI
4 implementation("net.java.dev.jna:jna:5.7.0@aar")
5 implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
6}

Sekarang, kita sudah bisa memanggil function getMessage dari Rust di Kotlin.

MainActivity.kt
icon
1import uniffi.greeting.getMessage
2
3class MainActivity : ComponentActivity() {
4 override fun onCreate(savedInstanceState: Bundle?) {
5 super.onCreate(savedInstanceState)
6 enableEdgeToEdge()
7 setContent {
8 GreetingAndroidTheme {
9 Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
10 Column(
11 verticalArrangement = Arrangement.Center,
12 horizontalAlignment = Alignment.CenterHorizontally,
13 modifier = Modifier.fillMaxSize().padding(innerPadding)
14 ) {
15 Text(
17 text = getMessage()
18 )
19 }
20 }
21 }
22 }
23 }
24}

AndroidAndroid

5. Automation Script

Agar tiap kali ada perubahan di library Rust-nya kita tidak perlu menjalankan command satu per-satu, lebih baik kita membuat script automasi untuk pembuatan Library Android.

Buat file baru bernama "build_android.sh" yang berisi:

build android.sh
1#!/bin/bash
2
3# Set up cargo-ndk and add the Android targets
4cargo install cargo-ndk
5rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android
6
7# Build the dylib
8cargo build
9
10# Build the Android libraries in jniLibs
11cargo ndk -o ../GreetingAndroid/app/src/main/jniLibs \
12 --manifest-path ./Cargo.toml \
13 -t armeabi-v7a \
14 -t arm64-v8a \
15 -t x86 \
16 -t x86_64 \
17 build --release
18
19# Create Kotlin bindings
20cargo run --bin uniffi-bindgen generate --library ./target/debug/libgreeting.dylib --language kotlin --out-dir ../GreetingAndroid/app/src/main/java/dev/alfin/greetingandroid
1chmod +x build_android.sh
2./build_android.sh

Sekarang, kita telah belajar bagaimana cara membuat sebuah library di Rust yang bisa digunakan di platform iOS dan Android. Selanjutnya mungkin kamu bisa kembangkan lagi library-nya agar bisa digunakan juga di Web atau di Desktop.

Oke mungkin itu saja yang bisa saya bagikan kali ini, kalau kamu merasa artikel ini bermanfaat silakan Like & Share artikel ini ke teman-teman kamu atau jika kamu punya pertanyaan, tulis aja di kolom komentar, Thank you! 😁 🙏

Source code lengkap dari tutorial ini bisa kalian akses di sini: https://github.com/alfinsyahruddin/greeting-demo

Cross Platform
Rust
Swift
Kotlin

Written by :
Alfin Syahruddin
Developer · Stock Trader · Libertarian · Freethinker

Always open to new ideas. 🕊️

Loading...

Related articles

Articles that you might want to read.

hero image
CI/CD aplikasi iOS dengan Fastlane dan Github Actions

Otomatisasi build, testing, screenshot, dan deployment aplikasi iOS ke Testflight & AppStore.

24 September 2023 · 9 Minutes
iOS Development
CI/CD
Fastlane
Github Actions
hero image
Gimana cara menambahkan fitur Multi Bahasa pada aplikasi React-mu?

Tutorial multilingual menggunakan react-i18next

21 August 2020 · 4 Minutes
React
Internationalization
Web Development
hero image
Tutorial membuat aplikasi Image Classification dengan Flutter dan Teachable Machine

Buat aplikasi AI pertama-mu dalam 10 menit ⚡️

17 January 2021 · 9 Minutes
Flutter
Artificial Intelligence
Image Classification
Teachable Machine
Cross Platform
All rights reserved © Alfin Syahruddin · 2019
RSS Feed