diff options
Diffstat (limited to 'components/rust/examples/modules/SConscript')
| -rw-r--r-- | components/rust/examples/modules/SConscript | 159 |
1 files changed, 159 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 |
