How to debug Rust libraries in Android application with Vs code LLDB

⚓ Rust    📅 2025-12-15    👤 surdeus    👁️ 4      

surdeus

Warning

This post was published 33 days ago. The information described in this article may have changed.

rust library
lib.rs ---define add、multiply function

#[no_mangle]
pub extern "C" fn add(left: u64, right: u64) -> u64 {
    left + right
}
#[no_mangle]
pub extern "C" fn multiply(left: u64, right: u64) -> u64 {
    left * right
}   
pub mod ffi;

android_jni.rs ---define jni ffi

#![cfg(target_os = "android")]

use jni::objects::JClass;
use jni::sys::{jint, jlong, JNI_VERSION_1_6, JavaVM};
use jni::JNIEnv;
use std::os::raw::c_void;
#[no_mangle]
#[allow(non_snake_case)]
fn catch_unwind_to_java<F>(env: &mut JNIEnv, f: F) -> Option<jlong>
where
    F: FnOnce() -> jlong,
{
    match std::panic::catch_unwind(std::panic::AssertUnwindSafe(f)) {
        Ok(v) => Some(v),
        Err(_) => {
            throw_runtime_exception(env, "panic in rustcall native code");
            None
        }
    }
}

/// Throw a Java `RuntimeException` with the given message.
fn throw_runtime_exception(env: &mut JNIEnv, msg: &str) {
    // Best-effort: if throwing fails, there's not much else we can do.
    let _ = env.throw_new("java/lang/RuntimeException", msg);
}

/// JNI: `public static native long add(long left, long right);`
#[no_mangle]
#[allow(non_snake_case)]
pub extern "system" fn Java_com_example_rustcall_RustCall_add(
    mut env: JNIEnv,
    _class: JClass,
    left: jlong,
    right: jlong,
) -> jlong {
    catch_unwind_to_java(&mut env, || crate::add(left as u64, right as u64) as jlong).unwrap_or(0)
}

pub extern "system" fn Java_com_example_rustcall_RustCall_multiply(
    mut env: JNIEnv,
    _class: JClass,
    left: jlong,
    right: jlong,
) -> jlong {
    catch_unwind_to_java(&mut env, || crate::multiply(left as u64, right as u64) as jlong)
        .unwrap_or(0)
}

mod.rs

// Platform-specific exports.
//
// IMPORTANT: each module is strictly gated via `cfg(...)` so that building for Android
// does not even compile iOS/OHOS code (and vice versa).

// Android JNI exports (enable with `--features android-jni`).
#[cfg(all(target_os = "android"))]
pub mod android_jni;

// iOS exports (C ABI; for Swift/ObjC you typically generate a header).
#[cfg(target_os = "ios")]
pub mod ios;

// HarmonyOS / OpenHarmony exports.
// NOTE: Rust `target_os` values for OHOS/OpenHarmony differ by toolchain; rather than
// using unknown `target_os = "..."`
// (which triggers `unexpected_cfgs` warnings), we gate this with:
// - a feature flag, and
// - explicit exclusion of Android/iOS so those builds never compile OHOS code.
#[cfg(all(not(target_os = "android"), not(target_os = "ios")))]
pub mod ohos;

Compilation command

cargo ndk -t arm64-v8a -t armeabi-v7a -t x86 -t x86_64 -o ./jniLibs build --release

image

Android Demo
Rust Call

package com.example.rustcall;

public final class RustCall {
    static {
        System.loadLibrary("rustcall");
    }

    private RustCall() {}

    public static native long add(long left, long right);

    public static native long multiply(long left, long right);
}

build.gradle.kts

android {
...
 buildTypes {
        debug {
            // Debug 构建:保持可调试 & 不混淆(方便 Java/Kotlin + Native 调试)
            isMinifyEnabled = false
            isDebuggable = true

            // 允许调试 native so(Android Studio/LLDB attach native 需要)
            isJniDebuggable = true

            // Debug 构建下:保留打进 APK 的所有 .so 的符号信息(覆盖所有 ABI)
            packaging {
                jniLibs {
                    keepDebugSymbols += setOf("**/librustcall.so")
                }
            }
        }
        release {
            isMinifyEnabled = false
            isDebuggable = true
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
            // Debug 构建下:保留打进 APK 的所有 .so 的符号信息(覆盖所有 ABI)
            packaging {
                jniLibs {
                    keepDebugSymbols += setOf("**/librustcall.so")
                }
            }
        }
    }
...
}

So how should I debug it?

1 post - 1 participant

Read full topic

🏷️ Rust_feed