bsp: support env shared package paths

This commit is contained in:
CYFS
2026-07-09 17:29:51 +08:00
committed by Rbb666
parent f12485a60e
commit dd7da0fd79
24 changed files with 391 additions and 101 deletions
+239
View File
@@ -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
+32
View File
@@ -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'))