Skip to content

Instantly share code, notes, and snippets.

@ylxs90
Created January 27, 2026 15:40
Show Gist options
  • Select an option

  • Save ylxs90/b5f4d1fb0b726ef8084d9893588bf9dc to your computer and use it in GitHub Desktop.

Select an option

Save ylxs90/b5f4d1fb0b726ef8084d9893588bf9dc to your computer and use it in GitHub Desktop.
rust common_lib
#!/bin/bash
mkdir -p project2/common_lib/src
mkdir -p project2/lib_a/src
mkdir -p project2/lib_b/src
cat <<'EOF' > project2/Cargo.toml
[workspace]
members = [
"common_lib",
"lib_a",
"lib_b",
]
resolver = "2"
[profile.release]
opt-level = 's'
lto = true
strip = true
codegen-units = 1
EOF
# common_lib 只编译成 cdylib
cat <<'EOF' > project2/common_lib/Cargo.toml
[package]
name = "common_lib"
version = "0.1.0"
edition = "2021"
[lib]
name = "common_lib"
crate-type = ["cdylib"]
[dependencies]
regex = "1.10.0"
EOF
cat <<'EOF' > project2/common_lib/src/lib.rs
use regex::Regex;
use std::ffi::{CStr, CString};
use std::os::raw::c_char;
#[no_mangle]
pub extern "C" fn get_regex_match_status(input: *const c_char) -> bool {
if input.is_null() {
return false;
}
unsafe {
let c_str = CStr::from_ptr(input);
if let Ok(s) = c_str.to_str() {
let re = Regex::new(r"world \w").unwrap();
re.is_match(s)
} else {
false
}
}
}
EOF
cat <<'EOF' > project2/lib_a/Cargo.toml
[package]
name = "lib_a"
version = "0.1.0"
edition = "2021"
[lib]
name = "lib_a"
crate-type = ["cdylib"]
[dependencies]
jni = "0.21.1"
EOF
cat <<'EOF' > project2/lib_a/build.rs
fn main() {
// 告诉链接器去链接 common_lib 动态库
println!("cargo:rustc-link-lib=dylib=common_lib");
// 告诉链接器在哪里找这个库(编译时)
let target_dir = std::env::var("CARGO_TARGET_DIR")
.unwrap_or_else(|_| "target".to_string());
let profile = std::env::var("PROFILE").unwrap();
let target = std::env::var("TARGET").unwrap();
println!("cargo:rustc-link-search=native={}/{}/{}", target_dir, target, profile);
}
EOF
cat <<'EOF' > project2/lib_a/src/lib.rs
use jni::JNIEnv;
use jni::objects::JClass;
use jni::sys::jstring;
use std::ffi::CString;
// 声明外部函数
extern "C" {
fn get_regex_match_status(input: *const std::os::raw::c_char) -> bool;
}
#[no_mangle]
pub extern "system" fn Java_com_example_LibA_getAString(env: JNIEnv, _class: JClass) -> jstring {
let input = CString::new("hello world a").unwrap();
let status = unsafe { get_regex_match_status(input.as_ptr()) };
let result = format!("Hello from Lib A (shared)! Status: {}", status);
env.new_string(result).expect("Couldn't create java string!").into_raw()
}
EOF
cat <<'EOF' > project2/lib_b/Cargo.toml
[package]
name = "lib_b"
version = "0.1.0"
edition = "2021"
[lib]
name = "lib_b"
crate-type = ["cdylib"]
[dependencies]
jni = "0.21.1"
EOF
cat <<'EOF' > project2/lib_b/build.rs
fn main() {
println!("cargo:rustc-link-lib=dylib=common_lib");
let target_dir = std::env::var("CARGO_TARGET_DIR")
.unwrap_or_else(|_| "target".to_string());
let profile = std::env::var("PROFILE").unwrap();
let target = std::env::var("TARGET").unwrap();
println!("cargo:rustc-link-search=native={}/{}/{}", target_dir, target, profile);
}
EOF
cat <<'EOF' > project2/lib_b/src/lib.rs
use jni::JNIEnv;
use jni::objects::JClass;
use jni::sys::jstring;
use std::ffi::CString;
extern "C" {
fn get_regex_match_status(input: *const std::os::raw::c_char) -> bool;
}
#[no_mangle]
pub extern "system" fn Java_com_example_LibB_getBString(env: JNIEnv, _class: JClass) -> jstring {
let input = CString::new("hello world b").unwrap();
let status = unsafe { get_regex_match_status(input.as_ptr()) };
let result = format!("Hello from Lib B (shared)! Status: {}", status);
env.new_string(result).expect("Couldn't create java string!").into_raw()
}
EOF
### need build common_lib first, then build lib_a, lib_b
# ll project2/target/aarch64-linux-android/release/ |grep so
# 1.4M Jan 27 23:08 libcommon_lib.so
# 275K Jan 27 23:08 liblib_a.so
# 275K Jan 27 23:08 liblib_b.so
#!/bin/bash
set -e
echo "Creating Full Project 1 (Independent dependencies)..."
# Clean up previous attempts if they exist
rm -rf project1
mkdir -p project1/lib_a/src
mkdir -p project1/lib_b/src
# --- Root Cargo.toml for Workspace ---
cat <<EOL > project1/Cargo.toml
[workspace]
members = [
"lib_a",
"lib_b",
]
[profile.release]
opt-level = 's'
lto = true
strip = true
codegen-units = 1
EOL
# --- lib_a files ---
cat <<EOL > project1/lib_a/Cargo.toml
[package]
name = "lib_a"
version = "0.1.0"
edition = "2021"
[lib]
name = "lib_a"
crate-type = ["cdylib"]
[dependencies]
regex = "1.10.0"
jni = "0.21.1"
EOL
cat <<EOL > project1/lib_a/src/lib.rs
use jni::JNIEnv;
use jni::objects::{JClass, JString};
use jni::sys::jstring;
use regex::Regex;
#[no_mangle]
pub extern "system" fn Java_com_example_LibA_getAString(env: JNIEnv, _class: JClass) -> jstring {
let re = Regex::new(r"world a").unwrap();
let result = format!("Hello from Lib A! Regex works: {}", re.is_match("hello world a"));
env.new_string(result).expect("Couldn't create java string!").into_raw()
}
EOL
# --- lib_b files ---
cat <<EOL > project1/lib_b/Cargo.toml
[package]
name = "lib_b"
version = "0.1.0"
edition = "2021"
[lib]
name = "lib_b"
crate-type = ["cdylib"]
[dependencies]
regex = "1.10.0"
jni = "0.21.1"
EOL
cat <<EOL > project1/lib_b/src/lib.rs
use jni::JNIEnv;
use jni::objects::{JClass, JString};
use jni::sys::jstring;
use regex::Regex;
#[no_mangle]
pub extern "system" fn Java_com_example_LibB_getBString(env: JNIEnv, _class: JClass) -> jstring {
let re = Regex::new(r"world b").unwrap();
let result = format!("Hello from Lib B! Regex works: {}", re.is_match("hello world b"));
env.new_string(result).expect("Couldn't create java string!").into_raw()
}
EOL
echo "Project 1 created successfully in ./project1"
# ll project1/target/aarch64-linux-android/release/ |grep so
# 1.4M Jan 27 22:26 liblib_a.so
# 1.4M Jan 27 22:26 liblib_a.so
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment