diff options
| author | zhang san <[email protected]> | 2025-12-08 18:34:25 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-12-08 18:34:25 +0800 |
| commit | 69980f8b9d29b38dbd4ddf6373b4b45f3a138409 (patch) | |
| tree | 21dd9a8ce80e3d30192e9ffa56ea39a199bae309 /components/rust/tools | |
| parent | cd1d47b87c5d47e131730e5506eb3ad77d357653 (diff) | |
Adding Rust Language Support for RT-Thread #10910
Diffstat (limited to 'components/rust/tools')
| -rw-r--r-- | components/rust/tools/__init__.py | 1 | ||||
| -rw-r--r-- | components/rust/tools/build_component.py | 200 | ||||
| -rw-r--r-- | components/rust/tools/build_support.py | 233 | ||||
| -rw-r--r-- | components/rust/tools/build_usrapp.py | 392 | ||||
| -rw-r--r-- | components/rust/tools/feature_config_component.py | 30 | ||||
| -rw-r--r-- | components/rust/tools/feature_config_examples.py | 26 |
6 files changed, 882 insertions, 0 deletions
diff --git a/components/rust/tools/__init__.py b/components/rust/tools/__init__.py new file mode 100644 index 0000000000..cdce003940 --- /dev/null +++ b/components/rust/tools/__init__.py @@ -0,0 +1 @@ +# User application build tools package
\ No newline at end of file diff --git a/components/rust/tools/build_component.py b/components/rust/tools/build_component.py new file mode 100644 index 0000000000..8b604f68b8 --- /dev/null +++ b/components/rust/tools/build_component.py @@ -0,0 +1,200 @@ +import os +import subprocess + + +# Configuration to feature mapping table for components +# This table defines which RT-Thread configurations should enable which component features +# All feature configurations are now defined in feature_config_component.py +CONFIG_COMPONENT_FEATURE_MAP = {} + + +class ComponentBuildError(Exception): + pass + + +def check_component_dependencies(component_dir, required_dependencies): + """ + Check if a component has the required dependencies + + Args: + component_dir: Component directory path + required_dependencies: List of dependency names to check + + Returns: + bool: True if all required dependencies are present + """ + if not component_dir or not required_dependencies: + return True + + cargo_toml_path = os.path.join(component_dir, 'Cargo.toml') + if not os.path.exists(cargo_toml_path): + return False + + try: + import toml + with open(cargo_toml_path, 'r') as f: + cargo_data = toml.load(f) + + dependencies = cargo_data.get('dependencies', {}) + + # Check if all required dependencies are present + for dep in required_dependencies: + if dep not in dependencies: + return False + + return True + + except Exception as e: + print(f"Warning: Failed to parse {cargo_toml_path}: {e}") + return False + + +def collect_component_features(has_func, component_dir=None): + """ + Collect component features based on RT-Thread configuration using extensible mapping table + + Args: + has_func: Function to check if a configuration is enabled + component_dir: Component directory to check dependencies (optional) + + Returns: + list: List of features to enable + """ + features = [] + + # Iterate through all configured mappings + for config_name, config_info in CONFIG_COMPONENT_FEATURE_MAP.items(): + # Check if this RT-Thread configuration is enabled + if has_func(config_name): + feature_name = config_info['feature'] + required_deps = config_info.get('dependencies', []) + + # If component_dir is provided, check dependencies + if component_dir: + if check_component_dependencies(component_dir, required_deps): + features.append(feature_name) + print(f"Enabling component feature '{feature_name}' for {config_name} in {os.path.basename(component_dir)}") + else: + # If no component_dir provided, enable for all (backward compatibility) + features.append(feature_name) + print(f"Enabling component feature '{feature_name}' for {config_name}") + + return features + +def cargo_build_component_staticlib(rust_dir, target, features, debug, rustflags=None, build_root=None): + """ + Build a Rust component as a static library using Cargo. + + Args: + rust_dir: Directory containing the Rust component + target: Rust target architecture + features: List of features to enable + debug: Whether this is a debug build + rustflags: Additional Rust compilation flags + build_root: Build root directory (if not provided, will raise error) + + Returns: + str: Path to the built library file, or None if build failed + """ + if not build_root: + raise ComponentBuildError("build_root parameter is required") + + build_root = os.path.abspath(build_root) + os.makedirs(build_root, exist_ok=True) + + env = os.environ.copy() + if rustflags: + prev = env.get("RUSTFLAGS", "").strip() + env["RUSTFLAGS"] = (prev + " " + rustflags).strip() if prev else rustflags + env["CARGO_TARGET_DIR"] = build_root + + cmd = [ + "cargo", "build", + "--target", target, + "--manifest-path", os.path.join(rust_dir, "Cargo.toml") + ] + + if not debug: + cmd.insert(2, "--release") + + if features: + cmd += ["--no-default-features", "--features", ",".join(features)] + + print("Building example component log (cargo)…") + res = subprocess.run(cmd, cwd=rust_dir, env=env, capture_output=True, text=True) + + if res.returncode != 0: + print("Warning: Example component build failed") + if res.stderr: + print(res.stderr) + return None + + mode = "debug" if debug else "release" + + # Try target-specific path first, then fallback to direct path + lib_path = os.path.join(build_root, target, mode, "libem_component_registry.a") + if os.path.exists(lib_path): + print("Example component log built successfully") + return lib_path + + print("Warning: Library not found at expected location") + print(f"Expected: {lib_path}") + return None + + +def build_example_component(cwd, has_func, rtconfig, build_root=None): + """ + Build the example component. + + Args: + cwd: Current working directory (component directory) + has_func: Function to check if a configuration is enabled + rtconfig: RT-Thread configuration module + build_root: Optional build root directory + + Returns: + tuple: (LIBS, LIBPATH, LINKFLAGS) for SCons + """ + LIBS = [] + LIBPATH = [] + LINKFLAGS = "" + + # Import build support functions + import sys + sys.path.append(os.path.join(cwd, '../rust/tools')) + from build_support import ( + detect_rust_target, + make_rustflags, + ) + + target = detect_rust_target(has_func, rtconfig) + + # Build mode and features + debug = bool(has_func('RUST_DEBUG_BUILD')) + + # Build the component registry + registry_dir = os.path.join(cwd, 'component_registry') + features = collect_component_features(has_func, registry_dir) + + rustflags = make_rustflags(rtconfig, target) + + rust_lib = cargo_build_component_staticlib( + rust_dir=registry_dir, + target=target, + features=features, + debug=debug, + rustflags=rustflags, + build_root=build_root + ) + + if rust_lib: + LIBS = ['em_component_registry'] + LIBPATH = [os.path.dirname(rust_lib)] + # Add LINKFLAGS to ensure component is linked into final binary + LINKFLAGS += " -Wl,--whole-archive -lem_component_registry -Wl,--no-whole-archive" + LINKFLAGS += " -Wl,--allow-multiple-definition" + print('Example component registry library linked successfully') + else: + print('Warning: Failed to build example component registry library') + + return LIBS, LIBPATH, LINKFLAGS
\ No newline at end of file diff --git a/components/rust/tools/build_support.py b/components/rust/tools/build_support.py new file mode 100644 index 0000000000..eb05fc1f29 --- /dev/null +++ b/components/rust/tools/build_support.py @@ -0,0 +1,233 @@ +import os +import subprocess + + +def _parse_cflags(cflags: str): + info = { + "march": None, + "mabi": None, + "rv_bits": None, # 32 or 64 + "has_f": False, + "has_d": False, + } + + if not cflags: + return info + + parts = cflags.split() + for flag in parts: + if flag.startswith("-march="): + info["march"] = flag.split("=", 1)[1] + if "rv32" in info["march"]: + info["rv_bits"] = 32 + elif "rv64" in info["march"]: + info["rv_bits"] = 64 + # crude feature detection + m = info["march"] + if m: + info["has_f"] = ("f" in m) + info["has_d"] = ("d" in m) + elif flag.startswith("-mabi="): + info["mabi"] = flag.split("=", 1)[1] + if info["mabi"] in ("ilp32d", "ilp32f", "lp64d", "lp64f"): + # floating-point ABI implies FPU availability + info["has_f"] = True + info["has_d"] = info["mabi"].endswith("d") + + return info + + +def detect_rust_target(has, rtconfig): + """ + Decide the Rust target triple based on RT-Thread Kconfig and rtconfig.*. + `has` is a callable: has("SYMBOL") -> bool + """ + # ARM Cortex-M + if has("ARCH_ARM"): + # FPU hints from flags/macros + cflags = getattr(rtconfig, "CFLAGS", "") + hard_float = "-mfloat-abi=hard" in cflags or has("ARCH_ARM_FPU") or has("ARCH_FPU_VFP") + + if has("ARCH_ARM_CORTEX_M3"): + return "thumbv7m-none-eabi" + if has("ARCH_ARM_CORTEX_M4") or has("ARCH_ARM_CORTEX_M7"): + return "thumbv7em-none-eabihf" if hard_float else "thumbv7em-none-eabi" + if has("ARCH_ARM_CORTEX_M33"): + # v8m.main + return "thumbv8m.main-none-eabi" + if has("ARCH_ARM_CORTEX_A"): + return "armv7a-none-eabi" + + # AArch64 + if has("ARCH_AARCH64") or has("ARCH_ARMV8") or has("ARCH_ARM64"): + if has("ARCH_CPU_FLOAT_ABI_SOFT"): + return "aarch64-unknown-none-softfloat" + return "aarch64-unknown-none" + + # RISC-V + if has("ARCH_RISCV32") or has("ARCH_RISCV64"): + cflags = getattr(rtconfig, "CFLAGS", "") + info = _parse_cflags(cflags) + + # fallback to Kconfig hint if march not present + rv_bits = info["rv_bits"] or (32 if has("ARCH_RISCV32") else 64) + + # ABI must carry f/d to actually use hard-float calling convention + abi = info["mabi"] or "" + abi_has_fp = abi.endswith("f") or abi.endswith("d") + + if rv_bits == 32: + # Only pick *f* target when ABI uses hard-float; otherwise use soft-float even if core has F/D + return "riscv32imafc-unknown-none-elf" if abi_has_fp else "riscv32imac-unknown-none-elf" + else: + # rv64: prefer gc (includes fd) only when ABI uses hard-float + return "riscv64gc-unknown-none-elf" if abi_has_fp else "riscv64imac-unknown-none-elf" + + # Fallback by ARCH string or CFLAGS + arch = getattr(rtconfig, "ARCH", None) + if arch: + arch_l = arch.lower() + if "aarch64" in arch_l: + return "aarch64-unknown-none" + if "arm" == arch_l or "armv7" in arch_l: + return "armv7a-none-eabi" + if "riscv32" in arch_l: + return "riscv32imac-unknown-none-elf" + if "riscv64" in arch_l or "risc-v" in arch_l: + # Many BSPs use "risc-v" token; assume 64-bit for virt64 + return "riscv64imac-unknown-none-elf" + + # Parse CFLAGS for hints + cflags = getattr(rtconfig, "CFLAGS", "") + if "-mcpu=cortex-m3" in cflags: + return "thumbv7m-none-eabi" + if "-mcpu=cortex-m4" in cflags or "-mcpu=cortex-m7" in cflags: + if "-mfpu=" in cflags and "-mfloat-abi=hard" in cflags: + return "thumbv7em-none-eabihf" + return "thumbv7em-none-eabi" + if "-march=rv32" in cflags: + march_val = None + mabi_val = None + for flag in cflags.split(): + if flag.startswith("-march="): + march_val = flag[len("-march="):] + elif flag.startswith("-mabi="): + mabi_val = flag[len("-mabi="):] + has_f_or_d = False + if march_val and any(x in march_val for x in ("f", "d")): + has_f_or_d = True + if mabi_val and any(x in mabi_val for x in ("f", "d")): + has_f_or_d = True + return "riscv32imafc-unknown-none-elf" if has_f_or_d else "riscv32imac-unknown-none-elf" + if "-march=rv64" in cflags: + march_val = None + mabi_val = None + for flag in cflags.split(): + if flag.startswith("-march="): + march_val = flag[len("-march="):] + elif flag.startswith("-mabi="): + mabi_val = flag[len("-mabi="):] + has_f_or_d = False + if mabi_val and (("lp64d" in mabi_val) or ("lp64f" in mabi_val)): + has_f_or_d = True + if march_val and any(x in march_val for x in ("f", "d")): + has_f_or_d = True + if mabi_val and any(x in mabi_val for x in ("f", "d")): + has_f_or_d = True + if has_f_or_d: + return "riscv64gc-unknown-none-elf" + return "riscv64imac-unknown-none-elf" + + return None + + +def make_rustflags(rtconfig, target: str): + rustflags = [ + "-C", "opt-level=z", + "-C", "panic=abort", + "-C", "relocation-model=static", + ] + + if "riscv" in target: + rustflags += [ + "-C", "code-model=medium", + "-C", "link-dead-code", + ] + # propagate march/mabi for consistency (use link-arg for staticlib builds – harmless) + cflags = getattr(rtconfig, "CFLAGS", "") + for flag in cflags.split(): + if flag.startswith("-march=") or flag.startswith("-mabi="): + rustflags += ["-C", f"link-arg={flag}"] + + if "thumb" in target or "aarch64" in target: + rustflags += ["-C", "link-arg=-nostartfiles"] + + return " ".join(rustflags) + + +def collect_features(has): + feats = [] + if has("RT_USING_SMP"): + feats.append("smp") + return feats + + +def verify_rust_toolchain(): + try: + r1 = subprocess.run(["rustc", "--version"], capture_output=True, text=True) + r2 = subprocess.run(["cargo", "--version"], capture_output=True, text=True) + return r1.returncode == 0 and r2.returncode == 0 + except Exception: + return False + + +def ensure_rust_target_installed(target: str): + try: + result = subprocess.run(["rustup", "target", "list", "--installed"], capture_output=True, text=True) + if result.returncode == 0 and target in result.stdout: + return True + print(f"Rust target '{target}' is not installed.") + print(f"Please install it with: rustup target add {target}") + except Exception: + print("Warning: Failed to check rustup target list (rustup missing?)") + return False + + +def cargo_build_staticlib(rust_dir: str, target: str, features, debug: bool, rustflags: str = None): + build_root = os.path.join((os.path.abspath(os.path.join(rust_dir, os.pardir, os.pardir))), "build", "rust") + target_dir = os.path.join(build_root, "target") + os.makedirs(build_root, exist_ok=True) + + env = os.environ.copy() + if rustflags: + prev = env.get("RUSTFLAGS", "").strip() + env["RUSTFLAGS"] = (prev + " " + rustflags).strip() if prev else rustflags + env["CARGO_TARGET_DIR"] = target_dir + + cmd = ["cargo", "build", "--target", target, "--manifest-path", os.path.join(rust_dir, "Cargo.toml")] + if not debug: + cmd.insert(2, "--release") + if features: + cmd += ["--no-default-features", "--features", ",".join(features)] + + print("Building Rust component (cargo)…") + res = subprocess.run(cmd, cwd=rust_dir, env=env, capture_output=True, text=True) + if res.returncode != 0: + print("Warning: Rust build failed") + if res.stderr: + print(res.stderr) + return None + + mode = "debug" if debug else "release" + lib_path = os.path.join(target_dir, target, mode, "librt_rust.a") + if os.path.exists(lib_path): + print("Rust component built successfully") + return lib_path + print("Warning: Library not found at expected location") + return None + + +def clean_rust_build(bsp_root: str, artifact_type: str = "rust"): + """Return the build directory path for SCons Clean operation""" + build_dir = os.path.join(bsp_root, "build", artifact_type) + return build_dir
\ No newline at end of file diff --git a/components/rust/tools/build_usrapp.py b/components/rust/tools/build_usrapp.py new file mode 100644 index 0000000000..9d97a60ffe --- /dev/null +++ b/components/rust/tools/build_usrapp.py @@ -0,0 +1,392 @@ +import os +import subprocess +import toml +import shutil + + +# Configuration to feature mapping table +# This table defines which RT-Thread configurations should enable which Rust features +# All feature configurations are now defined in feature_config_examples.py +CONFIG_FEATURE_MAP = {} + +# Application directory to Kconfig mapping table +# This table defines which Kconfig options control which application directories +APP_CONFIG_MAP = { + 'fs': 'RT_RUST_EXAMPLE_FS', + 'loadlib': 'RT_RUST_EXAMPLE_LOADLIB', + 'mutex': 'RT_RUST_EXAMPLE_MUTEX', + 'param': 'RT_RUST_EXAMPLE_PARAM', + 'queue': 'RT_RUST_EXAMPLE_QUEUE', + 'semaphore': 'RT_RUST_EXAMPLE_SEMAPHORE', + 'thread': 'RT_RUST_EXAMPLE_THREAD' +} + + +def should_build_app(app_dir, has_func): + """ + Check if an application should be built based on Kconfig configuration + + Args: + app_dir: Application directory path + has_func: Function to check if a configuration is enabled + + Returns: + bool: True if the application should be built + """ + # Get the application name from the directory + app_name = os.path.basename(app_dir) + + # Check if there's a specific Kconfig option for this app + if app_name in APP_CONFIG_MAP: + config_option = APP_CONFIG_MAP[app_name] + return has_func(config_option) + + # If no specific config found, check if applications are enabled in general + return has_func('RT_RUST_BUILD_APPLICATIONS') + + +def check_app_dependencies(app_dir, required_dependencies): + """ + Check if an application has the required dependencies + + Args: + app_dir: Application directory path + required_dependencies: List of dependency names to check + + Returns: + bool: True if all required dependencies are present + """ + if not app_dir or not required_dependencies: + return True + + cargo_toml_path = os.path.join(app_dir, 'Cargo.toml') + if not os.path.exists(cargo_toml_path): + return False + + try: + with open(cargo_toml_path, 'r') as f: + cargo_data = toml.load(f) + + dependencies = cargo_data.get('dependencies', {}) + + # Check if all required dependencies are present + for dep in required_dependencies: + if dep not in dependencies: + return False + + return True + + except Exception as e: + print(f"Warning: Failed to parse {cargo_toml_path}: {e}") + return False + + +def collect_features(has_func, app_dir=None): + """ + Collect Rust features based on RT-Thread configuration using extensible mapping table + + Args: + has_func: Function to check if a configuration is enabled + app_dir: Application directory to check dependencies (optional) + + Returns: + list: List of features to enable + """ + features = [] + + # Iterate through all configured mappings + for config_name, config_info in CONFIG_FEATURE_MAP.items(): + # Check if this RT-Thread configuration is enabled + if has_func(config_name): + feature_name = config_info['feature'] + required_deps = config_info.get('dependencies', []) + + # If app_dir is provided, check dependencies + if app_dir: + if check_app_dependencies(app_dir, required_deps): + features.append(feature_name) + print(f"Enabling feature '{feature_name}' for {config_name} in {os.path.basename(app_dir)}") + else: + # If no app_dir provided, enable for all (backward compatibility) + features.append(feature_name) + print(f"Enabling feature '{feature_name}' for {config_name}") + + return features + + + + + +class UserAppBuildError(Exception): + """User application build error exception""" + pass + + +def parse_cargo_toml(cargo_toml_path): + """ + Parse Cargo.toml file to extract library name and library type + + Args: + cargo_toml_path: Path to Cargo.toml file + + Returns: + tuple: (lib_name, is_staticlib) + """ + try: + with open(cargo_toml_path, 'r') as f: + cargo_data = toml.load(f) + + package_name = cargo_data.get('package', {}).get('name') + if not package_name: + raise UserAppBuildError(f"No package name found in {cargo_toml_path}") + + lib_config = cargo_data.get('lib', {}) + crate_type = lib_config.get('crate-type', []) + is_staticlib = 'staticlib' in crate_type + + # Use lib name if specified, otherwise use package name + lib_name = lib_config.get('name', package_name) + + return lib_name, is_staticlib + + except Exception as e: + raise UserAppBuildError(f"Failed to parse {cargo_toml_path}: {e}") + + +def discover_user_apps(base_dir): + """ + Discover all user application directories + + Args: + base_dir: Base directory path + + Returns: + list: List of directories containing Cargo.toml + """ + user_apps = [] + + for root, dirs, files in os.walk(base_dir): + if 'Cargo.toml' in files: + if 'target' in root or 'build' in root: + continue + user_apps.append(root) + + return user_apps + + +def build_user_app(app_dir, target, debug, rustflags, build_root, features=None): + """ + Build a single user application + + Args: + app_dir: Application directory + target: Rust target architecture + debug: Whether this is a debug build + rustflags: Rust compilation flags + build_root: Build root directory + features: List of features to enable + + Returns: + tuple: (success, lib_name, lib_path) + """ + try: + cargo_toml_path = os.path.join(app_dir, 'Cargo.toml') + lib_name, is_staticlib = parse_cargo_toml(cargo_toml_path) + + if not is_staticlib: + return False, None, None + + env = os.environ.copy() + env['RUSTFLAGS'] = rustflags + env['CARGO_TARGET_DIR'] = build_root + + cmd = ['cargo', 'build', '--target', target] + if not debug: + cmd.append('--release') + + # Add features if specified + if features: + cmd.extend(['--features', ','.join(features)]) + + print(f"Building example user app {lib_name} (cargo)…") + result = subprocess.run(cmd, cwd=app_dir, env=env, + capture_output=True, text=True) + + if result.returncode != 0: + print(f"Failed to build user app in {app_dir}") + print(f"Command: {' '.join(cmd)}") + print(f"Return code: {result.returncode}") + print(f"STDOUT: {result.stdout}") + print(f"STDERR: {result.stderr}") + return False, None, None + + lib_file = find_library_file(build_root, target, lib_name, debug) + if lib_file: + # Return the library name for linking + return True, lib_name, lib_file + else: + print(f"Library file not found for lib {lib_name}") + return False, None, None + + except Exception as e: + print(f"Exception occurred while building user app in {app_dir}: {e}") + return False, None, None + + +def find_library_file(build_root, target, lib_name, debug): + """ + Find the generated library file + + Args: + build_root: Build root directory + target: Rust target architecture + lib_name: Library name + debug: Whether this is a debug build + + Returns: + str: Library file path, or None if not found + """ + profile = "debug" if debug else "release" + + possible_names = [ + f"lib{lib_name}.a", + f"lib{lib_name.replace('-', '_')}.a" + ] + + search_paths = [ + os.path.join(build_root, target, profile), + os.path.join(build_root, target, profile, "deps") + ] + + for search_path in search_paths: + if not os.path.exists(search_path): + continue + + for name in possible_names: + lib_path = os.path.join(search_path, name) + if os.path.exists(lib_path): + return lib_path + + return None + + +def build_all_user_apps(base_dir, target, debug, rustflags, build_root, has_func): + """ + Build all user applications + + Args: + base_dir: User applications base directory + target: Rust target architecture + debug: Whether this is a debug build + rustflags: Rust compilation flags + build_root: Build root directory + has_func: Function to check if a configuration is enabled + + Returns: + tuple: (LIBS, LIBPATH, success_count, total_count) + """ + LIBS = [] + LIBPATH = [] + success_count = 0 + + user_apps = discover_user_apps(base_dir) + total_count = len(user_apps) + + for app_dir in user_apps: + # Check if this application should be built based on Kconfig + if not should_build_app(app_dir, has_func): + app_name = os.path.basename(app_dir) + print(f"Skipping {app_name} (disabled in Kconfig)") + continue + + # Collect features for this specific app + features = collect_features(has_func, app_dir) + success, lib_name, lib_path = build_user_app(app_dir, target, debug, rustflags, build_root, features) + + if success and lib_path: + app_name = os.path.basename(app_dir) + print(f"Example user app {app_name} built successfully") + LIBS.append(lib_name) + lib_dir = os.path.dirname(lib_path) + if lib_dir not in LIBPATH: + LIBPATH.append(lib_dir) + success_count += 1 + + return LIBS, LIBPATH, success_count, total_count + + +def generate_linkflags(LIBS, LIBPATH): + """ + Generate link flags + + Args: + LIBS: List of library names + LIBPATH: List of library paths + + Returns: + str: Link flags string + """ + if not LIBS or not LIBPATH: + return "" + + linkflags = f" -L{LIBPATH[0]} -Wl,--whole-archive" + for lib in LIBS: + linkflags += f" -l{lib}" + linkflags += " -Wl,--no-whole-archive -Wl,--allow-multiple-definition" + + return linkflags + + +def clean_user_apps_build(build_root): + """ + Clean user applications build artifacts + + Args: + build_root: Build root directory + """ + if os.path.exists(build_root): + shutil.rmtree(build_root) + + +def build_example_usrapp(cwd, has_func, rtconfig, build_root=None): + """ + Build the example user applications. + + Args: + cwd: Current working directory (usrapp directory) + has_func: Function to check if a configuration is enabled + rtconfig: RT-Thread configuration module + build_root: Optional build root directory + + Returns: + tuple: (LIBS, LIBPATH, LINKFLAGS) for SCons + """ + LIBS = [] + LIBPATH = [] + LINKFLAGS = "" + + try: + # Import build support functions + import sys + sys.path.append(os.path.join(cwd, '../rust/tools')) + import build_support as rust_build_support + + target = rust_build_support.detect_rust_target(has_func, rtconfig) + debug = bool(has_func('RUST_DEBUG_BUILD')) + rustflags = rust_build_support.make_rustflags(rtconfig, target) + LIBS, LIBPATH, success_count, total_count = build_all_user_apps( + cwd, target, debug, rustflags, build_root, has_func + ) + + if success_count == 0 and total_count > 0: + print(f'Warning: Failed to build all {total_count} user applications') + elif success_count > 0: + LINKFLAGS = generate_linkflags(LIBS, LIBPATH) + print(f'Example user apps linked successfully') + + except UserAppBuildError as e: + print(f'Error: {e}') + except Exception as e: + print(f'Unexpected error during user apps build: {e}') + + return LIBS, LIBPATH, LINKFLAGS
\ No newline at end of file diff --git a/components/rust/tools/feature_config_component.py b/components/rust/tools/feature_config_component.py new file mode 100644 index 0000000000..221d529abe --- /dev/null +++ b/components/rust/tools/feature_config_component.py @@ -0,0 +1,30 @@ +import sys +import os +from building import * +cwd = GetCurrentDir() +sys.path.append(os.path.join(cwd, 'tools')) +from build_component import CONFIG_COMPONENT_FEATURE_MAP + +def setup_all_component_features(): + """ + Setup all component feature mappings. + This function configures which RT-Thread configurations should enable which component features. + """ + + CONFIG_COMPONENT_FEATURE_MAP.update({ + 'RUST_LOG_COMPONENT': { + 'feature': 'enable-log', + 'dependencies': ['em_component_log'], + 'description': 'Enable Rust logging component integration' + }, + }) + + print("All component feature mappings have been configured!") + + +if __name__ == "__main__": + setup_all_component_features() + print(f"Total component configurations: {len(CONFIG_COMPONENT_FEATURE_MAP)}") + print("Available component configurations:") + for config, info in CONFIG_COMPONENT_FEATURE_MAP.items(): + print(f" {config}: {info['feature']} - {info['description']}")
\ No newline at end of file diff --git a/components/rust/tools/feature_config_examples.py b/components/rust/tools/feature_config_examples.py new file mode 100644 index 0000000000..1e4befa604 --- /dev/null +++ b/components/rust/tools/feature_config_examples.py @@ -0,0 +1,26 @@ +import sys +import os +from building import * +cwd = GetCurrentDir() +sys.path.append(os.path.join(cwd, 'tools')) +from build_usrapp import CONFIG_FEATURE_MAP + +def setup_all_example_features(): + + CONFIG_FEATURE_MAP.update({ + 'RUST_LOG_COMPONENT': { + 'feature': 'enable-log', + 'dependencies': ['em_component_log'], + 'description': 'Enable Rust logging component integration' + }, + }) + + print("All example feature mappings have been configured!") + + +if __name__ == "__main__": + setup_all_example_features() + print(f"Total configurations: {len(CONFIG_FEATURE_MAP)}") + print("Available configurations:") + for config, info in CONFIG_FEATURE_MAP.items(): + print(f" {config}: {info['feature']} - {info['description']}")
\ No newline at end of file |
