mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-02-06 14:01:39 +00:00
200 lines
6.5 KiB
Python
200 lines
6.5 KiB
Python
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 |