summaryrefslogtreecommitdiff
path: root/components/rust/examples/modules
diff options
context:
space:
mode:
Diffstat (limited to 'components/rust/examples/modules')
-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
4 files changed, 238 insertions, 0 deletions
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