diff options
| author | CYFS <[email protected]> | 2026-06-10 17:13:05 +0800 |
|---|---|---|
| committer | Rbb666 <[email protected]> | 2026-07-09 17:29:51 +0800 |
| commit | dd7da0fd799dd34dd0db781dcfdab7c4b2dedf39 (patch) | |
| tree | 45ff82241e8c29b5c1ce205a7ada4142ced4ab11 /tools | |
| parent | f12485a60e3019e2b2a97c1db6bd2c1456dded37 (diff) | |
bsp: support env shared package paths
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/env_package.py | 239 | ||||
| -rw-r--r-- | tools/mkdist.py | 32 |
2 files changed, 271 insertions, 0 deletions
diff --git a/tools/env_package.py b/tools/env_package.py new file mode 100644 index 0000000000..2f80cceb18 --- /dev/null +++ b/tools/env_package.py @@ -0,0 +1,239 @@ +# +# File : env_package.py +# This file is part of RT-Thread RTOS +# +# SPDX-License-Identifier: GPL-2.0+ +# +# Change Logs: +# Date Author Notes +# 2026-06-12 CYFS Add shared package path helpers +# + +import fnmatch +import os + + +def _same_path(path_a, path_b): + return os.path.normcase(os.path.abspath(path_a)) == os.path.normcase(os.path.abspath(path_b)) + + +def _format_path(path, relative_to=None, pathsep=None): + if relative_to: + path = os.path.relpath(path, relative_to) + + if pathsep: + path = path.replace(os.path.sep, pathsep) + if os.path.altsep: + path = path.replace(os.path.altsep, pathsep) + + return path + + +def _marker_exists(package_path, marker): + if not marker: + return True + + if isinstance(marker, (list, tuple)): + for item in marker: + if not _marker_exists(package_path, item): + return False + return True + + return os.path.exists(os.path.join(package_path, marker)) + + +def _unique_paths(paths): + unique_paths = [] + seen = set() + + for path in paths: + if not path: + continue + + key = os.path.normcase(os.path.abspath(path)) + if key in seen: + continue + + seen.add(key) + unique_paths.append(path) + + return unique_paths + + +def package_root_candidates(bsp_root): + bsp_root = os.path.abspath(bsp_root) + ancestors = [] + current = bsp_root + + while True: + if _is_rt_thread_bsp_dir(current): + break + + ancestors.append(current) + + parent = os.path.dirname(current) + if _same_path(parent, current): + break + + current = parent + + library_roots = [os.path.join(root, 'libraries') for root in ancestors] + package_roots = [os.path.join(root, 'packages') for root in ancestors] + + return _unique_paths(library_roots + package_roots) + + +def package_candidates(bsp_root, package_name, extra_candidates=None): + candidates = [] + for root in package_root_candidates(bsp_root): + candidates.append(os.path.join(root, package_name)) + + if extra_candidates: + candidates.extend(extra_candidates) + + return _unique_paths(candidates) + + +def find_package_path(bsp_root, package_name, marker=None, extra_candidates=None, + relative_to=None, pathsep=None): + candidates = package_candidates(bsp_root, package_name, extra_candidates) + existing_paths = [] + + for path in candidates: + if not os.path.isdir(path): + continue + + existing_paths.append(path) + if _marker_exists(path, marker): + return _format_path(path, relative_to, pathsep) + + if existing_paths: + return _format_path(existing_paths[0], relative_to, pathsep) + + fallback_path = os.path.join(os.path.abspath(bsp_root), 'packages', package_name) + return _format_path(fallback_path, relative_to, pathsep) + + +def package_exists(bsp_root, package_name, marker=None): + path = find_package_path(bsp_root, package_name, marker=marker) + return os.path.isdir(path) and _marker_exists(path, marker) + + +def packages_available(bsp_root, package_names): + for package_name in package_names: + if not package_exists(bsp_root, package_name): + return False + + return True + + +def _package_name_match(name, package_name=None, package_prefix=None, package_pattern=None): + if package_name and name != package_name: + return False + + if package_prefix and not name.startswith(package_prefix): + return False + + if package_pattern and not fnmatch.fnmatch(name, package_pattern): + return False + + return True + + +def find_package_root(bsp_root, package_name=None, package_prefix=None, + package_pattern=None, marker=None): + for root in package_root_candidates(bsp_root): + if not os.path.isdir(root): + continue + + if package_name: + package_path = os.path.join(root, package_name) + if os.path.isdir(package_path) and _marker_exists(package_path, marker): + return root + continue + + try: + names = os.listdir(root) + except OSError: + continue + + for name in names: + package_path = os.path.join(root, name) + if not os.path.isdir(package_path): + continue + if not _package_name_match(name, package_name, package_prefix, package_pattern): + continue + if _marker_exists(package_path, marker): + return root + + return None + + +def is_libraries_package(package_path): + return os.path.basename(os.path.dirname(os.path.abspath(package_path))).lower() == 'libraries' + + +def _get_existing_libraries_path(root): + exact_path = os.path.join(root, 'libraries') + if os.path.isdir(exact_path): + return exact_path + + try: + for name in os.listdir(root): + path = os.path.join(root, name) + if name.lower() == 'libraries' and os.path.isdir(path): + return path + except OSError: + pass + + return None + + +def _is_rt_thread_bsp_dir(path): + parent = os.path.dirname(path) + return ( + os.path.basename(path).lower() == 'bsp' + and os.path.isdir(os.path.join(parent, 'bsp')) + and os.path.isfile(os.path.join(parent, 'include', 'rtdef.h')) + ) + + +def find_libraries_path_upward(bsp_root): + current = os.path.abspath(bsp_root) + + while True: + libraries_path = _get_existing_libraries_path(current) + if libraries_path: + return libraries_path + + if _is_rt_thread_bsp_dir(current): + return None + + parent = os.path.dirname(current) + if _same_path(parent, current): + return None + + current = parent + + +def is_hal_sdk_package_bridge(package_path): + if os.path.isdir(os.path.join(package_path, '.git')): + return False + + sconscript_path = os.path.join(package_path, 'SConscript') + if not os.path.isfile(sconscript_path): + return False + + try: + with open(sconscript_path, 'r') as f: + content = f.read() + return ( + 'hal-sdk package source not found' in content + and ( + 'source_candidates' in content + or '_find_hal_sdk_libraries_path' in content + or 'libraries_path_prefix' in content + ) + ) + except Exception: + return False diff --git a/tools/mkdist.py b/tools/mkdist.py index ddbbc3dc51..472f54a936 100644 --- a/tools/mkdist.py +++ b/tools/mkdist.py @@ -22,6 +22,7 @@ # 2017-10-04 Bernard The first version # 2025-01-07 ZhaoCake components copy and gen doc # 2025-03-02 ZhaoCake Add MkDist_Strip +# 2026-06-10 CYFS Copy shared hal-sdk package libraries for dist import os @@ -29,6 +30,8 @@ import subprocess import shutil from shutil import ignore_patterns from SCons.Script import * +from env_package import find_libraries_path_upward +from env_package import is_hal_sdk_package_bridge def do_copy_file(src, dst): # check source file @@ -164,6 +167,33 @@ def bsp_update_kconfig_library(dist_dir): line = line.replace('../libraries', 'libraries') f.write(line) +def bsp_copy_hal_sdk_package_libraries(bsp_root, dist_dir): + packages_dir = os.path.join(dist_dir, 'packages') + if not os.path.isdir(packages_dir): + return + + libraries_path = find_libraries_path_upward(bsp_root) + if not libraries_path: + return + + copied = False + for package_name in os.listdir(packages_dir): + package_path = os.path.join(packages_dir, package_name) + if not os.path.isdir(package_path): + continue + if not is_hal_sdk_package_bridge(package_path): + continue + + source_path = os.path.join(libraries_path, package_name) + if not os.path.isdir(source_path): + print('warning: hal-sdk package library not found: %s' % source_path) + continue + + if not copied: + print('=> hal-sdk package libraries') + copied = True + bsp_copy_files(source_path, os.path.join(dist_dir, 'libraries', package_name)) + def zip_dist(dist_dir, dist_name): import zipfile @@ -199,6 +229,8 @@ def MkDist(program, BSP_ROOT, RTT_ROOT, Env, project_name, project_path): dist_handle = Env['dist_handle'] dist_handle(BSP_ROOT, dist_dir) + bsp_copy_hal_sdk_package_libraries(BSP_ROOT, dist_dir) + # copy tools directory print('=> components') do_copy_folder(os.path.join(RTT_ROOT, 'components'), os.path.join(rtt_dir_path, 'components')) |
