summaryrefslogtreecommitdiff
path: root/components/rust/examples
diff options
context:
space:
mode:
authorzhang san <[email protected]>2025-12-08 18:34:25 +0800
committerGitHub <[email protected]>2025-12-08 18:34:25 +0800
commit69980f8b9d29b38dbd4ddf6373b4b45f3a138409 (patch)
tree21dd9a8ce80e3d30192e9ffa56ea39a199bae309 /components/rust/examples
parentcd1d47b87c5d47e131730e5506eb3ad77d357653 (diff)
Adding Rust Language Support for RT-Thread #10910
Diffstat (limited to 'components/rust/examples')
-rw-r--r--components/rust/examples/Kconfig104
-rw-r--r--components/rust/examples/SConscript22
-rw-r--r--components/rust/examples/application/SConscript70
-rw-r--r--components/rust/examples/application/fs/Cargo.toml17
-rw-r--r--components/rust/examples/application/fs/src/lib.rs73
-rw-r--r--components/rust/examples/application/loadlib/Cargo.toml12
-rw-r--r--components/rust/examples/application/loadlib/src/lib.rs34
-rw-r--r--components/rust/examples/application/mutex/Cargo.toml12
-rw-r--r--components/rust/examples/application/mutex/src/lib.rs45
-rw-r--r--components/rust/examples/application/param/Cargo.toml13
-rw-r--r--components/rust/examples/application/param/src/lib.rs26
-rw-r--r--components/rust/examples/application/queue/Cargo.toml12
-rw-r--r--components/rust/examples/application/queue/src/lib.rs51
-rw-r--r--components/rust/examples/application/semaphore/Cargo.toml12
-rw-r--r--components/rust/examples/application/semaphore/src/lib.rs50
-rw-r--r--components/rust/examples/application/thread/Cargo.toml12
-rw-r--r--components/rust/examples/application/thread/src/lib.rs41
-rw-r--r--components/rust/examples/component/SConscript71
-rw-r--r--components/rust/examples/component/component_registry/Cargo.toml19
-rw-r--r--components/rust/examples/component/component_registry/src/lib.rs43
-rw-r--r--components/rust/examples/component/log/Cargo.toml15
-rw-r--r--components/rust/examples/component/log/src/lib.rs30
-rw-r--r--components/rust/examples/component/log/src/logging.rs96
-rw-r--r--components/rust/examples/modules/SConscript159
-rw-r--r--components/rust/examples/modules/example_lib/.gitignore37
-rw-r--r--components/rust/examples/modules/example_lib/Cargo.toml12
-rw-r--r--components/rust/examples/modules/example_lib/src/lib.rs30
27 files changed, 1118 insertions, 0 deletions
diff --git a/components/rust/examples/Kconfig b/components/rust/examples/Kconfig
new file mode 100644
index 0000000000..cd18690868
--- /dev/null
+++ b/components/rust/examples/Kconfig
@@ -0,0 +1,104 @@
+menuconfig RT_USING_RUST_EXAMPLES
+ bool "Enable Rust Examples"
+ depends on RT_USING_RUST
+ default n
+ help
+ Enable Rust example applications, components, and modules.
+
+if RT_USING_RUST_EXAMPLES
+
+ config RT_RUST_BUILD_ALL_EXAMPLES
+ bool "Build All Examples"
+ default n
+ help
+ Build all available Rust examples.
+
+ menu "Application Examples"
+ config RT_RUST_BUILD_APPLICATIONS
+ bool "Build Application Examples"
+ default y
+ depends on RT_USING_FINSH
+ help
+ Build Rust application examples.
+
+ if RT_RUST_BUILD_APPLICATIONS
+ config RT_RUST_EXAMPLE_FS
+ bool "File System Example"
+ default n
+ help
+ File system operations example.
+
+ config RT_RUST_EXAMPLE_LOADLIB
+ bool "Dynamic Library Loading Example"
+ default n
+ depends on RT_USING_MODULE
+ help
+ Dynamic library loading and usage example.
+
+ config RT_RUST_EXAMPLE_MUTEX
+ bool "Mutex Example"
+ default y
+ help
+ Mutex synchronization example.
+
+ config RT_RUST_EXAMPLE_PARAM
+ bool "Parameter Example"
+ default y
+ help
+ Basic parameter handling example.
+
+ config RT_RUST_EXAMPLE_QUEUE
+ bool "Queue Example"
+ default y
+ help
+ Message queue example.
+
+ config RT_RUST_EXAMPLE_SEMAPHORE
+ bool "Semaphore Example"
+ default y
+ help
+ Semaphore synchronization example.
+
+ config RT_RUST_EXAMPLE_THREAD
+ bool "Thread Example"
+ default y
+ help
+ Thread creation and management example.
+ endif
+ endmenu
+
+ menu "Component Examples"
+ config RT_RUST_BUILD_COMPONENTS
+ bool "Build Component Examples"
+ default y
+ help
+ Build Rust component examples.
+
+ if RT_RUST_BUILD_COMPONENTS
+ config RUST_LOG_COMPONENT
+ bool "Auto-initialize Rust log component"
+ default y
+ help
+ Automatically initialize Rust log component during RT-Thread startup.
+ endif
+ endmenu
+
+ menu "Module Examples"
+ config RT_RUST_BUILD_MODULES
+ bool "Build Module Examples"
+ default n
+ depends on RT_USING_MODULE
+ help
+ Build Rust dynamic module examples.
+
+ if RT_RUST_BUILD_MODULES
+ config RT_RUST_MODULE_SIMPLE_MODULE
+ bool "Simple Module"
+ default y
+ help
+ Basic dynamic module template.
+
+ endif
+ endmenu
+
+endif \ No newline at end of file
diff --git a/components/rust/examples/SConscript b/components/rust/examples/SConscript
new file mode 100644
index 0000000000..1ac5417eff
--- /dev/null
+++ b/components/rust/examples/SConscript
@@ -0,0 +1,22 @@
+# RT-Thread building script for Rust examples
+
+import os
+from building import *
+
+Import('rtconfig')
+
+cwd = GetCurrentDir()
+group = []
+entries = os.listdir(cwd)
+
+subdirs = ['application', 'component', 'modules']
+
+for subdir in subdirs:
+ if subdir in entries:
+ result = SConscript(os.path.join(subdir, 'SConscript'))
+ if isinstance(result, (list, tuple)):
+ group.extend(result)
+ else:
+ group.append(result)
+
+Return('group') \ No newline at end of file
diff --git a/components/rust/examples/application/SConscript b/components/rust/examples/application/SConscript
new file mode 100644
index 0000000000..c6c4de3db8
--- /dev/null
+++ b/components/rust/examples/application/SConscript
@@ -0,0 +1,70 @@
+import os
+import sys
+from building import *
+
+cwd = GetCurrentDir()
+
+# Import usrapp build module and build support
+sys.path.append(os.path.join(cwd, '../../tools'))
+from build_usrapp import build_example_usrapp
+from build_support import clean_rust_build
+
+
+def _has(sym: str) -> bool:
+ try:
+ return bool(GetDepend([sym]))
+ except Exception:
+ return bool(GetDepend(sym))
+
+
+def load_extended_feature_configs():
+ """
+ Load extended feature configurations if available.
+ This allows users to add custom configuration mappings.
+ """
+ try:
+ from feature_config_examples import setup_all_example_features
+ setup_all_example_features()
+ print("Extended feature configurations loaded successfully.")
+ except ImportError:
+ print("Using default feature configurations.")
+
+group = []
+
+if not _has('RT_RUST_BUILD_APPLICATIONS'):
+ Return('group')
+
+# Load extended feature configurations
+load_extended_feature_configs()
+
+src = []
+LIBS = []
+LIBPATH = []
+LINKFLAGS = ""
+
+if GetOption('clean'):
+ app_build_dir = clean_rust_build(Dir('#').abspath, "example_usrapp")
+ if os.path.exists(app_build_dir):
+ print(f'Registering {app_build_dir} for cleanup')
+ Clean('.', app_build_dir)
+ else:
+ print('No example_usrapp build artifacts to clean')
+else:
+ import rtconfig
+ LIBS, LIBPATH, LINKFLAGS = build_example_usrapp(
+ cwd=cwd,
+ has_func=_has,
+ rtconfig=rtconfig,
+ build_root=os.path.join(Dir('#').abspath, "build", "example_usrapp")
+ )
+
+group = DefineGroup(
+ 'example_usrapp',
+ src,
+ depend=['RT_USING_RUST'],
+ LIBS=LIBS,
+ LIBPATH=LIBPATH,
+ LINKFLAGS=LINKFLAGS
+)
+
+Return('group') \ No newline at end of file
diff --git a/components/rust/examples/application/fs/Cargo.toml b/components/rust/examples/application/fs/Cargo.toml
new file mode 100644
index 0000000000..2556b5f0a4
--- /dev/null
+++ b/components/rust/examples/application/fs/Cargo.toml
@@ -0,0 +1,17 @@
+[package]
+name = "em_fs"
+version = "0.1.0"
+edition = "2021"
+
+[lib]
+name = "em_fs"
+crate-type = ["staticlib"]
+
+[features]
+default = []
+enable-log = ["em_component_log/enable-log"]
+
+[dependencies]
+rt-rust = { path = "../../../core" }
+rt_macros = { path = "../../../rt_macros" }
+em_component_log = { path = "../../component/log"} \ No newline at end of file
diff --git a/components/rust/examples/application/fs/src/lib.rs b/components/rust/examples/application/fs/src/lib.rs
new file mode 100644
index 0000000000..53cf8561d1
--- /dev/null
+++ b/components/rust/examples/application/fs/src/lib.rs
@@ -0,0 +1,73 @@
+
+/*
+ * Copyright (c) 2006-2025, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author notes
+ * 2025-10-20 foxglove Rust file operation test.
+ * 2025-10-29 foxglove Updated to demonstrate new modular macro interface
+ */
+#![no_std]
+
+extern crate alloc;
+
+use rt_macros::msh_cmd_export;
+use rt_rust::{fs, println};
+use rt_rust::param::Param;
+use em_component_log::{info, error};
+
+#[msh_cmd_export(name = "rust_file_demo", desc = "Rust example app.")]
+fn main(_param: Param) {
+ println!("[rust_file_test] start");
+
+ let mut file = match fs::OpenOptions::new()
+ .read(true)
+ .write(true)
+ .create(true)
+ .append(false)
+ .truncate(true)
+ .open("test.txt")
+ {
+ Ok(f) => {
+ info!("open test.txt ok");
+ f
+ }
+ Err(e) => {
+ error!("open error: {:?}", e);
+ return;
+ }
+ };
+
+ if let Err(e) = file.write_all("Hello from FS wrapper!\n") {
+ error!("write_all error: {:?}", e);
+ return;
+ }
+ info!("write_all done");
+
+ if let Err(e) = file.flush() {
+ error!("flush error: {:?}", e);
+ } else {
+ info!("flush ok");
+ }
+
+ match file.read_to_string() {
+ Ok(s) => info!("read_back: {}", s),
+ Err(e) => error!("read_to_string error: {:?}", e),
+ }
+
+ if let Err(e) = file.set_len(5) {
+ error!("truncate error: {:?}", e);
+ } else {
+ info!("truncate to 5 ok");
+ }
+
+ if let Err(e) = file.close() {
+ error!("close error: {:?}", e);
+ } else {
+ info!("close ok");
+ }
+
+ info!("[rust_file_test] end");
+}
diff --git a/components/rust/examples/application/loadlib/Cargo.toml b/components/rust/examples/application/loadlib/Cargo.toml
new file mode 100644
index 0000000000..1e1065f91a
--- /dev/null
+++ b/components/rust/examples/application/loadlib/Cargo.toml
@@ -0,0 +1,12 @@
+[package]
+name = "em_loadlib"
+version = "0.1.0"
+edition = "2021"
+
+[lib]
+name = "em_loadlib"
+crate-type = ["staticlib"]
+
+[dependencies]
+rt-rust = { path = "../../../core" }
+rt_macros = { path = "../../../rt_macros" } \ No newline at end of file
diff --git a/components/rust/examples/application/loadlib/src/lib.rs b/components/rust/examples/application/loadlib/src/lib.rs
new file mode 100644
index 0000000000..d60175f5fa
--- /dev/null
+++ b/components/rust/examples/application/loadlib/src/lib.rs
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2006-2025, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author notes
+ * 2025-10-10 foxglove load library example
+ * 2025-10-29 foxglove Updated to demonstrate new modular macro interface
+ */
+#![no_std]
+
+extern crate alloc;
+
+use rt_macros::msh_cmd_export;
+use rt_rust::println;
+use rt_rust::get_libfn;
+use core::ffi::{c_int, c_char};
+use rt_rust::param::Param;
+
+#[msh_cmd_export(name = "rust_dl_demo", desc = "Rust dynamic library demo")]
+fn main(_param: Param) {
+ println!("\n=== Dynamic Library Demo ===");
+
+ get_libfn!("/hello.mo", "main", my_hello, ());
+ my_hello();
+
+ get_libfn!("/libmylib.mo", "rust_mylib_add", my_add, c_int, a: c_int, b: c_int);
+ let s = my_add(15, 20);
+ println!("my_add(15, 20) = {}", s);
+
+ get_libfn!("/libmylib.mo", "rust_mylib_println", my_println, (), s: *const c_char);
+ my_println(b"rustlib: Hello World\0".as_ptr() as *const c_char);
+}
diff --git a/components/rust/examples/application/mutex/Cargo.toml b/components/rust/examples/application/mutex/Cargo.toml
new file mode 100644
index 0000000000..188ad1ba1d
--- /dev/null
+++ b/components/rust/examples/application/mutex/Cargo.toml
@@ -0,0 +1,12 @@
+[package]
+name = "em_mutex"
+version = "0.1.0"
+edition = "2021"
+
+[lib]
+name = "em_mutex"
+crate-type = ["staticlib"]
+
+[dependencies]
+rt-rust = { path = "../../../core" }
+rt_macros = { path = "../../../rt_macros" }
diff --git a/components/rust/examples/application/mutex/src/lib.rs b/components/rust/examples/application/mutex/src/lib.rs
new file mode 100644
index 0000000000..3160ab6b76
--- /dev/null
+++ b/components/rust/examples/application/mutex/src/lib.rs
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2006-2025, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author notes
+ * 2025-10-10 foxglove mutex test demo
+ * 2025-10-29 foxglove Updated to demonstrate new modular macro interface
+ */
+#![no_std]
+
+extern crate alloc;
+
+use alloc::sync::Arc;
+use core::time::Duration;
+use rt_macros::msh_cmd_export;
+use rt_rust::mutex::Mutex;
+use rt_rust::param::Param;
+use rt_rust::println;
+use rt_rust::thread;
+use rt_rust::time;
+
+#[msh_cmd_export(name = "rust_mutex_demo", desc = "Rust example app.")]
+fn main(_param: Param) {
+ let counter = Arc::new(Mutex::new(0).unwrap());
+ let run = move || loop {
+ time::sleep(Duration::new(2, 0));
+ {
+ let mut c = counter.lock().unwrap();
+ *c += 1;
+ println!("{}", *c);
+ }
+ };
+
+ let _ = thread::Thread::new()
+ .name("thread 1")
+ .stack_size(2048)
+ .start(run.clone());
+ time::sleep(Duration::new(1, 0));
+ let _ = thread::Thread::new()
+ .name("thread 2")
+ .stack_size(2048)
+ .start(run.clone());
+}
diff --git a/components/rust/examples/application/param/Cargo.toml b/components/rust/examples/application/param/Cargo.toml
new file mode 100644
index 0000000000..aa3daae8c9
--- /dev/null
+++ b/components/rust/examples/application/param/Cargo.toml
@@ -0,0 +1,13 @@
+[package]
+name = "em_param"
+version = "0.1.0"
+edition = "2021"
+
+[lib]
+name = "em_param"
+crate-type = ["staticlib"]
+
+[dependencies]
+rt-rust = { path = "../../../core" }
+rt_macros = { path = "../../../rt_macros" }
+
diff --git a/components/rust/examples/application/param/src/lib.rs b/components/rust/examples/application/param/src/lib.rs
new file mode 100644
index 0000000000..209daa14f1
--- /dev/null
+++ b/components/rust/examples/application/param/src/lib.rs
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2006-2025, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author notes
+ * 2025-10-10 foxglove param test demo
+ * 2025-10-29 foxglove Updated to demonstrate new modular macro interface
+ */
+#![no_std]
+
+extern crate alloc;
+
+use alloc::string::String;
+use rt_macros::{rt_app_export, msh_cmd_export};
+use rt_rust::param::Param;
+use rt_rust::println;
+
+// 演示新的模块化宏接口 - 使用 msh_cmd_export 导出参数测试命令
+#[msh_cmd_export(name = "rust_param_demo", desc = "Rust parameter demo")]
+fn main(param: Param) {
+ for i in param {
+ println!("{}", String::from_utf8_lossy(&*i))
+ }
+}
diff --git a/components/rust/examples/application/queue/Cargo.toml b/components/rust/examples/application/queue/Cargo.toml
new file mode 100644
index 0000000000..4ea390d183
--- /dev/null
+++ b/components/rust/examples/application/queue/Cargo.toml
@@ -0,0 +1,12 @@
+[package]
+name = "em_queue"
+version = "0.1.0"
+edition = "2021"
+
+[lib]
+name = "em_queue"
+crate-type = ["staticlib"]
+
+[dependencies]
+rt-rust = { path = "../../../core" }
+rt_macros = { path = "../../../rt_macros" }
diff --git a/components/rust/examples/application/queue/src/lib.rs b/components/rust/examples/application/queue/src/lib.rs
new file mode 100644
index 0000000000..fda7c7c0f3
--- /dev/null
+++ b/components/rust/examples/application/queue/src/lib.rs
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2006-2025, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author notes
+ * 2025-10-10 foxglove queue test demo
+ * 2025-10-29 foxglove Updated to demonstrate new modular macro interface
+ */
+#![no_std]
+
+extern crate alloc;
+
+use alloc::string::String;
+use alloc::sync::Arc;
+use core::time::Duration;
+use rt_macros::msh_cmd_export;
+use rt_rust::queue::Queue;
+use rt_rust::param::Param;
+use rt_rust::println;
+use rt_rust::thread;
+use rt_rust::time;
+
+#[msh_cmd_export(name = "rust_queue_demo", desc = "Rust example app.")]
+fn main(_param: Param) {
+ let send = Arc::new(Queue::new(2).unwrap());
+ let recv = send.clone();
+
+ let _ = thread::Thread::new()
+ .name("thread 1")
+ .stack_size(1024)
+ .start(move || {
+ loop {
+ time::sleep(Duration::new(1, 0));
+ send.send(String::from("msg"), 0).unwrap();
+ }
+ });
+ time::sleep(Duration::new(1, 0));
+ let _ = thread::Thread::new()
+ .name("thread 2")
+ .stack_size(1024)
+ .start(move || {
+ loop {
+ println!("waiting!");
+ let a = recv.recv_wait_forever().unwrap();
+ println!("recv {}", a);
+ }
+ });
+}
+
diff --git a/components/rust/examples/application/semaphore/Cargo.toml b/components/rust/examples/application/semaphore/Cargo.toml
new file mode 100644
index 0000000000..16aa670145
--- /dev/null
+++ b/components/rust/examples/application/semaphore/Cargo.toml
@@ -0,0 +1,12 @@
+[package]
+name = "em_sem"
+version = "0.1.0"
+edition = "2021"
+
+[lib]
+name = "em_sem"
+crate-type = ["staticlib"]
+
+[dependencies]
+rt-rust = { path = "../../../core" }
+rt_macros = { path = "../../../rt_macros" }
diff --git a/components/rust/examples/application/semaphore/src/lib.rs b/components/rust/examples/application/semaphore/src/lib.rs
new file mode 100644
index 0000000000..986acd1957
--- /dev/null
+++ b/components/rust/examples/application/semaphore/src/lib.rs
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2006-2025, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author notes
+ * 2025-10-10 foxglove semaphore test demo
+ * 2025-10-29 foxglove Updated to demonstrate new modular macro interface
+ */
+#![no_std]
+
+extern crate alloc;
+
+use alloc::sync::Arc;
+use core::time::Duration;
+use rt_macros::msh_cmd_export;
+use rt_rust::sem::Semaphore;
+use rt_rust::param::Param;
+use rt_rust::println;
+use rt_rust::thread;
+use rt_rust::time;
+
+#[msh_cmd_export(name = "rust_sem_demo", desc = "Rust example app.")]
+fn main(_param: Param) {
+ let send = Arc::new(Semaphore::new().unwrap());
+ let recv = send.clone();
+
+ let _ = thread::Thread::new()
+ .name("thread 1")
+ .stack_size(1024)
+ .start(move || {
+ loop {
+ time::sleep(Duration::new(1, 0));
+ send.release()
+ }
+ });
+ time::sleep(Duration::new(1, 0));
+ let _ = thread::Thread::new()
+ .name("thread 2")
+ .stack_size(1024)
+ .start(move || {
+ loop {
+ println!("waiting!");
+ recv.take_wait_forever().unwrap();
+ println!("recv a sem!")
+ }
+ });
+}
+
diff --git a/components/rust/examples/application/thread/Cargo.toml b/components/rust/examples/application/thread/Cargo.toml
new file mode 100644
index 0000000000..a85e275c77
--- /dev/null
+++ b/components/rust/examples/application/thread/Cargo.toml
@@ -0,0 +1,12 @@
+[package]
+name = "em_thread"
+version = "0.1.0"
+edition = "2021"
+
+[lib]
+name = "em_thread"
+crate-type = ["staticlib"]
+
+[dependencies]
+rt-rust = { path = "../../../core" }
+rt_macros = { path = "../../../rt_macros" }
diff --git a/components/rust/examples/application/thread/src/lib.rs b/components/rust/examples/application/thread/src/lib.rs
new file mode 100644
index 0000000000..7f2cdf04c3
--- /dev/null
+++ b/components/rust/examples/application/thread/src/lib.rs
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2006-2025, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author notes
+ * 2025-10-10 foxglove thread test demo
+ * 2025-10-29 foxglove Updated to demonstrate new modular macro interface
+ */
+#![no_std]
+
+use core::time::Duration;
+use rt_macros::msh_cmd_export;
+use rt_rust::param::Param;
+use rt_rust::println;
+use rt_rust::thread;
+use rt_rust::time;
+
+#[msh_cmd_export(name = "rust_thread_demo", desc = "Rust example app.")]
+fn main(_param: Param) {
+ let _ = thread::Thread::new()
+ .name("thread 1")
+ .stack_size(1024)
+ .start(move || {
+ loop {
+ println!("thread a will sleep 1s");
+ time::sleep(Duration::new(1, 0));
+ }
+ });
+
+ let _ = thread::Thread::new()
+ .name("thread 2")
+ .stack_size(1024)
+ .start(move || {
+ loop {
+ println!("thread b will sleep 3s");
+ time::sleep(Duration::new(3, 0));
+ }
+ });
+}
diff --git a/components/rust/examples/component/SConscript b/components/rust/examples/component/SConscript
new file mode 100644
index 0000000000..40d11c0446
--- /dev/null
+++ b/components/rust/examples/component/SConscript
@@ -0,0 +1,71 @@
+import os
+import sys
+from building import *
+
+cwd = GetCurrentDir()
+
+# Import component build module and build support
+sys.path.append(os.path.join(cwd, '../../tools'))
+from build_component import build_example_component
+from build_support import clean_rust_build
+
+# Load feature configurations
+try:
+ from feature_config_component import setup_all_component_features
+ setup_all_component_features()
+except ImportError:
+ print("Warning: Could not load component feature configurations")
+
+
+def _has(sym: str) -> bool:
+ """Helper function to check if a configuration symbol is enabled."""
+ try:
+ return bool(GetDepend([sym]))
+ except Exception:
+ return bool(GetDepend(sym))
+
+
+# Early return if Rust or log component is not enabled
+if not _has('RT_USING_RUST'):
+ group = []
+ Return('group')
+
+if not _has('RUST_LOG_COMPONENT'):
+ group = []
+ Return('group')
+
+# Source files – component glue code if needed
+src = []
+LIBS = []
+LIBPATH = []
+LINKFLAGS = ""
+
+# Handle clean operation
+if GetOption('clean'):
+ comp_build_dir = clean_rust_build(Dir('#').abspath, "example_component")
+ if os.path.exists(comp_build_dir):
+ print(f'Registering {comp_build_dir} for cleanup')
+ Clean('.', comp_build_dir)
+ else:
+ print('No example_component build artifacts to clean')
+else:
+ # Build the component using the extracted build module
+ import rtconfig
+ LIBS, LIBPATH, LINKFLAGS = build_example_component(
+ cwd=cwd,
+ has_func=_has,
+ rtconfig=rtconfig,
+ build_root=os.path.join(Dir('#').abspath, "build", "example_component")
+ )
+
+# Define component group for SCons
+group = DefineGroup(
+ 'example_component_log',
+ src,
+ depend=['RT_USING_RUST'],
+ LIBS=LIBS,
+ LIBPATH=LIBPATH,
+ LINKFLAGS=LINKFLAGS
+)
+
+Return('group') \ No newline at end of file
diff --git a/components/rust/examples/component/component_registry/Cargo.toml b/components/rust/examples/component/component_registry/Cargo.toml
new file mode 100644
index 0000000000..64ec88c2d4
--- /dev/null
+++ b/components/rust/examples/component/component_registry/Cargo.toml
@@ -0,0 +1,19 @@
+[package]
+name = "em_component_registry"
+version = "0.1.0"
+edition = "2021"
+
+[lib]
+name = "em_component_registry"
+crate-type = ["staticlib"]
+
+[dependencies]
+rt-rust = { path = "../../../core" }
+rt_macros = { path = "../../../rt_macros" }
+
+# Optional dependencies - only included when features are enabled
+em_component_log = { path = "../log", optional = true }
+
+[features]
+default = []
+enable-log = ["em_component_log", "em_component_log/enable-log"] \ No newline at end of file
diff --git a/components/rust/examples/component/component_registry/src/lib.rs b/components/rust/examples/component/component_registry/src/lib.rs
new file mode 100644
index 0000000000..beff2df698
--- /dev/null
+++ b/components/rust/examples/component/component_registry/src/lib.rs
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2006-2025, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author notes
+ * 2025-10-25 foxglove Component registry for unified component registration
+ * 2025-10-29 foxglove Updated to demonstrate new modular macro interface
+ */
+#![no_std]
+
+extern crate alloc;
+
+/* Demonstrate the new modular macro interface */
+use rt_macros::rt_component_export;
+use rt_rust::param::{Param, ParamItem};
+use rt_rust::println;
+
+/* Re-export component functionality for other modules */
+#[cfg(feature = "enable-log")]
+pub use em_component_log::*;
+#[cfg(feature = "enable-log")]
+use em_component_log::logging::Level;
+
+/** Unified component registration entrypoint */
+#[cfg(feature = "enable-log")]
+#[rt_component_export(name = "rust_component_registry")]
+fn init_registry_component() {
+ println!("[logging component init] hello world");
+ log!(Level::Info, "hello world");
+ info!("hello world");
+ warn!("hello world");
+ error!("hello world");
+ trace!("hello world");
+ debug!("hello world");
+}
+
+/** Provide a no-op implementation when no component feature is enabled */
+#[cfg(not(feature = "enable-log"))]
+pub extern "C" fn component_init() {
+ /* Empty implementation to ensure the library still links */
+}
diff --git a/components/rust/examples/component/log/Cargo.toml b/components/rust/examples/component/log/Cargo.toml
new file mode 100644
index 0000000000..901772b771
--- /dev/null
+++ b/components/rust/examples/component/log/Cargo.toml
@@ -0,0 +1,15 @@
+[package]
+name = "em_component_log"
+version = "0.1.0"
+edition = "2021"
+
+[lib]
+name = "em_component_log"
+crate-type = ["rlib", "staticlib"]
+
+[features]
+default = []
+enable-log = []
+
+[dependencies]
+rt-rust = { path = "../../../core" }
diff --git a/components/rust/examples/component/log/src/lib.rs b/components/rust/examples/component/log/src/lib.rs
new file mode 100644
index 0000000000..ff7e75c32f
--- /dev/null
+++ b/components/rust/examples/component/log/src/lib.rs
@@ -0,0 +1,30 @@
+
+/*
+ * Copyright (c) 2006-2025, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author notes
+ * 2025-10-23 foxglove log component demo
+ */
+#![no_std]
+
+extern crate alloc;
+
+/* When the `enable-log` feature is enabled, expose logging module and helpers */
+#[cfg(feature = "enable-log")]
+pub mod logging;
+#[cfg(feature = "enable-log")]
+use rt_rust::println;
+#[cfg(feature = "enable-log")]
+use crate::logging::Level;
+
+/* Import panic handler parameters from rt_rust library */
+use rt_rust::param::{Param, ParamItem};
+
+/* Provide a no-op implementation when the `enable-log` feature is disabled */
+#[cfg(not(feature = "enable-log"))]
+pub extern "C" fn component_init() {
+ /* Empty implementation to ensure the library still links */
+}
diff --git a/components/rust/examples/component/log/src/logging.rs b/components/rust/examples/component/log/src/logging.rs
new file mode 100644
index 0000000000..ccbf8ee1e2
--- /dev/null
+++ b/components/rust/examples/component/log/src/logging.rs
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2006-2024, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author notes
+ * 2025-10-20 foxglove micro rust log component
+ */
+/* Basic logging primitives and console output helpers */
+use alloc::string::String;
+use rt_rust::println;
+
+#[repr(usize)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub enum Level {
+ Error = 1,
+ Warn = 2,
+ Info = 3,
+ Debug = 4,
+ Trace = 5,
+}
+
+/* Top-level logging macro */
+#[macro_export]
+macro_rules! log {
+ ($level:expr, $($arg:tt)*) => ({
+ $crate::logging::_log($level, format_args!($($arg)*));
+ });
+}
+
+/* Error-level logging */
+#[macro_export]
+macro_rules! error {
+ ($($arg:tt)*) => ({
+ $crate::logging::_log($crate::logging::Level::Error, format_args!($($arg)*));
+ });
+}
+
+/* Warning-level logging */
+#[macro_export]
+macro_rules! warn {
+ ($($arg:tt)*) => ({
+ $crate::logging::_log($crate::logging::Level::Warn, format_args!($($arg)*));
+ });
+}
+
+/* Info-level logging */
+#[macro_export]
+macro_rules! info {
+ ($($arg:tt)*) => ({
+ $crate::logging::_log($crate::logging::Level::Info, format_args!($($arg)*));
+ });
+}
+
+/* Debug-level logging */
+#[macro_export]
+macro_rules! debug {
+ ($($arg:tt)*) => ({
+ $crate::logging::_log($crate::logging::Level::Debug, format_args!($($arg)*));
+ });
+}
+
+/* Trace-level logging */
+#[macro_export]
+macro_rules! trace {
+ ($($arg:tt)*) => ({
+ $crate::logging::_log($crate::logging::Level::Trace, format_args!($($arg)*));
+ });
+}
+
+/* Internal logging handler: formats message and prints with color */
+pub fn _log(level: Level, args: core::fmt::Arguments) {
+ use core::fmt::Write;
+ use rt_rust::time;
+ let mut s = String::new();
+ write!(&mut s, "[{:?}][{:?}]", level, time::get_time()).unwrap();
+ write!(&mut s, "{}", args).unwrap();
+ match level {
+ Level::Error => {
+ println!("\x1b[1;31m{}\x1b[0m", s);
+ }
+ Level::Warn => {
+ println!("\x1b[1;33m{}\x1b[0m", s);
+ }
+ Level::Info => {
+ println!("\x1b[1;32m{}\x1b[0m", s);
+ }
+ Level::Debug => {
+ println!("\x1b[1;34m{}\x1b[0m", s);
+ }
+ Level::Trace => {
+ println!("\x1b[1;30m{}\x1b[0m", s);
+ }
+ }
+}
diff --git a/components/rust/examples/modules/SConscript b/components/rust/examples/modules/SConscript
new file mode 100644
index 0000000000..98e57d1fd9
--- /dev/null
+++ b/components/rust/examples/modules/SConscript
@@ -0,0 +1,159 @@
+import os
+import sys
+import subprocess
+import toml
+from building import *
+
+cwd = GetCurrentDir()
+
+RUSTC_FLAGS = {
+ "linker": "-C linker=ld.lld",
+ "panic": "-C panic=abort",
+}
+
+CARGO_CMD = {
+ "base": "cargo build",
+ "build_std": "-Z build-std=core,alloc,panic_abort",
+ "target_flag": "--target",
+ "target_arch": "%s",
+ "release_profile": "--release",
+ "debug_profile": "", # No additional flag for debug mode
+}
+
+tools_dir = os.path.join(cwd, '..', '..', 'tools')
+sys.path.insert(0, tools_dir)
+
+from build_support import detect_rust_target, ensure_rust_target_installed, clean_rust_build
+
+def _has(sym: str) -> bool:
+ """Helper function to check if a configuration symbol is enabled"""
+ try:
+ return bool(GetDepend([sym]))
+ except Exception:
+ return bool(GetDepend(sym))
+
+def detect_target_for_dynamic_modules():
+ """
+ Detect the appropriate Rust target for dynamic modules.
+ For dynamic modules, we need Linux targets instead of bare-metal targets.
+ """
+ if detect_rust_target is not None:
+ try:
+ import rtconfig
+ bare_metal_target = detect_rust_target(_has, rtconfig)
+
+ if bare_metal_target:
+ if "riscv64" in bare_metal_target:
+ return "riscv64gc-unknown-linux-gnu"
+ elif "riscv32" in bare_metal_target:
+ return "riscv32gc-unknown-linux-gnu"
+ elif "aarch64" in bare_metal_target:
+ return "aarch64-unknown-linux-gnu"
+ elif "arm" in bare_metal_target or "thumb" in bare_metal_target:
+ return "armv7-unknown-linux-gnueabihf"
+ except Exception as e:
+ print(f"Error: Target detection failed: {e}")
+ raise RuntimeError(f"Failed to detect Rust target for dynamic modules: {e}")
+
+ print("Error: Unable to detect appropriate Rust target for dynamic modules")
+ raise RuntimeError("Target detection failed - no valid target found")
+
+def build_rust_module(module_dir, build_root):
+ """Build a Rust dynamic module with automatic target detection"""
+ cargo_toml_path = os.path.join(module_dir, 'Cargo.toml')
+ if not os.path.exists(cargo_toml_path):
+ return [], [], ""
+
+ with open(cargo_toml_path, 'r') as f:
+ cargo_config = toml.load(f)
+
+ module_name = cargo_config['package']['name']
+
+ # Detect target automatically based on the current configuration
+ target = detect_target_for_dynamic_modules()
+ print(f"Building Rust module '{module_name}' for target: {target}")
+
+ # Detect debug mode from rtconfig (same as main rust/SConscript)
+ debug = bool(_has('RUST_DEBUG_BUILD'))
+ build_mode = "debug" if debug else "release"
+ print(f"Building in {build_mode} mode")
+
+ # Use global RUSTFLAGS configuration for dynamic modules
+ rustflags = " ".join(RUSTC_FLAGS.values())
+
+ # Verify that the target is installed
+ if ensure_rust_target_installed is not None:
+ if not ensure_rust_target_installed(target):
+ print(f"Error: Rust target '{target}' is not installed")
+ print(f"Please install it with: rustup target add {target}")
+ return [], [], ""
+ else:
+ print(f"Warning: Cannot verify if target '{target}' is installed")
+
+ # Set up build environment
+ env = os.environ.copy()
+ env['RUSTFLAGS'] = rustflags
+ env['CARGO_TARGET_DIR'] = build_root
+
+ # Build the module with configurable parameters using dictionary configuration
+ build_cmd = [
+ CARGO_CMD["base"].split()[0], # 'cargo'
+ CARGO_CMD["base"].split()[1], # 'build'
+ CARGO_CMD["target_flag"], # '--target'
+ target, # actual target architecture
+ ]
+
+ # Add profile flag based on debug mode
+ profile_flag = CARGO_CMD["debug_profile"] if debug else CARGO_CMD["release_profile"]
+ if profile_flag:
+ build_cmd.append(profile_flag)
+
+ # Add build-std flag if specified
+ if CARGO_CMD["build_std"]:
+ build_std_parts = CARGO_CMD["build_std"].split()
+ build_cmd.extend(build_std_parts)
+
+ try:
+ subprocess.run(build_cmd, cwd=module_dir, env=env, check=True, capture_output=True)
+ lib_dir = os.path.join(build_root, target, build_mode)
+ return [module_name], [lib_dir], ""
+ except subprocess.CalledProcessError:
+ return [], [], ""
+
+# Check dependencies
+if not _has('RT_RUST_BUILD_MODULES'):
+ Return([])
+
+build_root = os.path.join(Dir('#').abspath, "build", "rust_modules")
+
+# Handle clean operation
+if GetOption('clean'):
+ if clean_rust_build is not None:
+ modules_build_dir = clean_rust_build(Dir('#').abspath, "rust_modules")
+ if os.path.exists(modules_build_dir):
+ print(f'Registering {modules_build_dir} for cleanup')
+ Clean('.', modules_build_dir)
+ else:
+ print('No rust_modules build artifacts to clean')
+ else:
+ print('Warning: clean_rust_build function not available')
+else:
+ # Build all Rust modules in subdirectories
+ modules_built = []
+ for item in os.listdir(cwd):
+ item_path = os.path.join(cwd, item)
+ if os.path.isdir(item_path) and os.path.exists(os.path.join(item_path, 'Cargo.toml')):
+ result = build_rust_module(item_path, build_root)
+ if result[0]:
+ modules_built.extend(result[0])
+
+ if modules_built:
+ print(f"Successfully built {len(modules_built)} Rust dynamic module(s): {', '.join(modules_built)}")
+
+group = DefineGroup(
+ 'rust_modules',
+ [],
+ depend=['RT_RUST_BUILD_MODULES']
+)
+
+Return('group') \ No newline at end of file
diff --git a/components/rust/examples/modules/example_lib/.gitignore b/components/rust/examples/modules/example_lib/.gitignore
new file mode 100644
index 0000000000..5f4fb2595d
--- /dev/null
+++ b/components/rust/examples/modules/example_lib/.gitignore
@@ -0,0 +1,37 @@
+# Rust build artifacts (now in build/rust)
+/target/
+**/*.rs.bk
+*.pdb
+
+# Cargo lock file (optional - uncomment if you want to exclude it)
+# Cargo.lock
+
+# Build directories
+/build/
+*.o
+*.a
+*.so
+*.dylib
+*.dll
+
+# IDE specific files
+.idea/
+.vscode/
+*.swp
+*.swo
+*~
+.DS_Store
+
+# Debug files
+*.dSYM/
+*.su
+*.idb
+*.pdb
+
+# Backup files
+*.bak
+*.tmp
+*.temp
+
+# Log files
+*.log \ No newline at end of file
diff --git a/components/rust/examples/modules/example_lib/Cargo.toml b/components/rust/examples/modules/example_lib/Cargo.toml
new file mode 100644
index 0000000000..e44aae2848
--- /dev/null
+++ b/components/rust/examples/modules/example_lib/Cargo.toml
@@ -0,0 +1,12 @@
+[workspace]
+
+[package]
+name = "examplelib"
+version = "0.1.0"
+edition = "2024"
+
+[lib]
+crate-type = ["cdylib"]
+
+[dependencies]
+rt-rust = { path = "../../.." } \ No newline at end of file
diff --git a/components/rust/examples/modules/example_lib/src/lib.rs b/components/rust/examples/modules/example_lib/src/lib.rs
new file mode 100644
index 0000000000..5f81c1553f
--- /dev/null
+++ b/components/rust/examples/modules/example_lib/src/lib.rs
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2006-2024, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date Author notes
+ * 2025-10-10 foxglove Basic library module template
+ */
+#![no_std]
+/* Bring rt-rust's println! macro into scope */
+use rt_rust::println;
+use core::ffi::{c_char, CStr};
+#[unsafe(no_mangle)]
+pub extern "C" fn rust_mylib_println(s: *const c_char) {
+ if s.is_null() {
+ println!("");
+ } else {
+ let cs = unsafe {CStr::from_ptr(s)};
+ match cs.to_str() {
+ Ok(msg) => println!("{}", msg),
+ Err(_) => println!("[invalid UTF-8]"),
+ }
+ }
+}
+
+#[unsafe(no_mangle)]
+pub extern "C" fn rust_mylib_add(a: usize, b: usize) -> usize {
+ a + b
+} \ No newline at end of file