diff options
Diffstat (limited to 'components/rust/examples/modules')
| -rw-r--r-- | components/rust/examples/modules/SConscript | 159 | ||||
| -rw-r--r-- | components/rust/examples/modules/example_lib/.gitignore | 37 | ||||
| -rw-r--r-- | components/rust/examples/modules/example_lib/Cargo.toml | 12 | ||||
| -rw-r--r-- | components/rust/examples/modules/example_lib/src/lib.rs | 30 |
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 |
