Skip to content

Commit 21414e8

Browse files
ZhaoCakeRbb666
authored andcommitted
[feat][tools]Only add used components to distubution package.
1 parent 8b482ae commit 21414e8

File tree

1 file changed

+217
-5
lines changed

1 file changed

+217
-5
lines changed

tools/mkdist.py

Lines changed: 217 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import shutil
2727
from shutil import ignore_patterns
2828
from SCons.Script import *
29+
import time
2930

3031
def do_copy_file(src, dst):
3132
# check source file
@@ -40,7 +41,6 @@ def do_copy_file(src, dst):
4041
shutil.copy2(src, dst)
4142

4243
def do_copy_folder(src_dir, dst_dir, ignore=None):
43-
import shutil
4444
# check source directory
4545
if not os.path.exists(src_dir):
4646
return
@@ -171,6 +171,215 @@ def zip_dist(dist_dir, dist_name):
171171

172172
zip.close()
173173

174+
def get_system_features():
175+
"""获取系统内置特性列表"""
176+
return {
177+
# 内核特性
178+
'components_init',
179+
'console',
180+
'cpu_usage_tracer',
181+
'heap',
182+
'slab',
183+
'mempool',
184+
'memtrace',
185+
'timer_soft',
186+
'event',
187+
'mailbox',
188+
'messagequeue',
189+
'mutex',
190+
'semaphore',
191+
'signals',
192+
'hook',
193+
'idle_hook',
194+
'thread',
195+
'cache',
196+
'debug',
197+
'device_ops',
198+
'overflow_check',
199+
'slab_as_heap',
200+
'user_main',
201+
'stdc_atomic',
202+
}
203+
204+
def parse_components_from_config(config_file):
205+
"""从 .config 文件解析启用的组件"""
206+
enabled_components = set()
207+
208+
if not os.path.exists(config_file):
209+
print(f"Error: {config_file} does not exist")
210+
return enabled_components
211+
212+
with open(config_file, 'r') as f:
213+
for line in f:
214+
line = line.strip()
215+
if line.startswith('CONFIG_'):
216+
if '=' in line:
217+
config = line.split('=')[0][7:] # 去掉 CONFIG_ 前缀
218+
if config.startswith('RT_USING_'):
219+
component = config[9:].lower() # 去掉 RT_USING_ 前缀
220+
enabled_components.add(component)
221+
return enabled_components
222+
223+
def scan_components_dir(RTT_ROOT):
224+
"""扫描组件目录结构,生成组件映射表"""
225+
components_map = {}
226+
components_root = os.path.join(RTT_ROOT, 'components')
227+
228+
def parse_kconfig(kconfig_file):
229+
"""解析 Kconfig 文件中的配置选项"""
230+
components = set()
231+
try:
232+
with open(kconfig_file, 'r') as f:
233+
content = f.read()
234+
# 查找 config RT_USING_XXX 形式的配置
235+
import re
236+
matches = re.finditer(r'config\s+RT_USING_(\w+)', content)
237+
for match in matches:
238+
component_name = match.group(1).lower()
239+
components.add(component_name)
240+
except Exception as e:
241+
print(f"Warning: Failed to parse {kconfig_file}: {str(e)}")
242+
return components
243+
244+
def get_relative_path(full_path):
245+
"""获取相对于 RTT_ROOT 的路径"""
246+
return os.path.relpath(os.path.dirname(full_path), RTT_ROOT)
247+
248+
# 扫描所有组件目录
249+
for root, dirs, files in os.walk(components_root):
250+
if 'Kconfig' in files:
251+
kconfig_path = os.path.join(root, 'Kconfig')
252+
component_configs = parse_kconfig(kconfig_path)
253+
rel_path = get_relative_path(kconfig_path)
254+
255+
# 将组件名称与路径关联
256+
for comp_name in component_configs:
257+
components_map[comp_name] = rel_path
258+
259+
return components_map
260+
261+
def get_component_path(component_name, RTT_ROOT):
262+
"""获取组件的实际路径"""
263+
# 获取动态组件映射
264+
dynamic_map = scan_components_dir(RTT_ROOT)
265+
return dynamic_map.get(component_name)
266+
267+
def generate_dist_doc(dist_dir, enabled_components, project_name, BSP_ROOT, RTT_ROOT):
268+
"""Generate distribution package documentation"""
269+
doc_lines = [] # Store document content in a list
270+
271+
# Basic information
272+
doc_lines.extend([
273+
"# RT-Thread Distribution Package\n",
274+
"\n## Basic Information\n\n",
275+
f"- Project Name: {project_name}\n",
276+
f"- Generation Time: {time.strftime('%Y-%m-%d %H:%M:%S')}\n",
277+
f"- BSP: {os.path.basename(BSP_ROOT)}\n",
278+
"\n## Components\n\n",
279+
"### Included Components:\n\n"
280+
])
281+
282+
# Add component information
283+
for comp in sorted(enabled_components):
284+
path = get_component_path(comp, RTT_ROOT)
285+
if path:
286+
doc_lines.append(f"- {comp}\n - Path: {path}\n")
287+
288+
# Add configuration information
289+
doc_lines.extend(["\n## Configuration\n\n"])
290+
config_file = os.path.join(BSP_ROOT, '.config')
291+
if os.path.exists(config_file):
292+
doc_lines.extend([
293+
"### Main Configuration Items:\n\n```\n"
294+
])
295+
with open(config_file, 'r') as f:
296+
for line in f:
297+
if line.startswith('CONFIG_'):
298+
doc_lines.append(line)
299+
doc_lines.append("```\n")
300+
301+
# Add simplified directory structure
302+
doc_lines.extend(["\n## Directory Structure\n\n```\n"])
303+
304+
# Show only top-level directories
305+
items = os.listdir(dist_dir)
306+
items.sort()
307+
for item in items:
308+
if item.startswith('.') or item == 'dist':
309+
continue
310+
path = os.path.join(dist_dir, item)
311+
if os.path.isdir(path):
312+
doc_lines.append(f"├── {item}/\n")
313+
else:
314+
doc_lines.append(f"├── {item}\n")
315+
316+
doc_lines.append("```\n")
317+
318+
# Add build instructions
319+
doc_lines.extend(["""
320+
## Build Instructions
321+
322+
1. Requirements:
323+
- Python 3.x
324+
- SCons build tool
325+
- Appropriate cross-compiler toolchain
326+
327+
2. Build Steps:
328+
```bash
329+
scons
330+
```
331+
332+
3. Clean Build:
333+
```bash
334+
scons -c
335+
```
336+
337+
## Notes
338+
339+
1. Make sure the toolchain environment variables are properly set
340+
2. To modify configuration, use menuconfig:
341+
```bash
342+
scons --menuconfig
343+
```
344+
345+
## License
346+
347+
See `COPYING` file for details.
348+
"""])
349+
350+
# Write documentation
351+
doc_file = os.path.join(dist_dir, 'dist_readme.md')
352+
with open(doc_file, 'w', encoding='utf-8') as f:
353+
f.writelines(doc_lines)
354+
355+
print(f"=> Generated distribution documentation: {doc_file}")
356+
357+
def components_copy_files(RTT_ROOT, rtt_dir_path, config_file):
358+
"""根据配置复制组件"""
359+
print('=> components (selective copy)')
360+
361+
# 获取启用的组件
362+
enabled_components = parse_components_from_config(config_file)
363+
if not enabled_components:
364+
print("Warning: No components found in config file")
365+
return enabled_components
366+
367+
# 复制每个启用的组件
368+
for comp_name in enabled_components:
369+
comp_path = get_component_path(comp_name, RTT_ROOT)
370+
if comp_path:
371+
src_path = os.path.join(RTT_ROOT, comp_path)
372+
dst_path = os.path.join(rtt_dir_path, comp_path)
373+
if os.path.exists(src_path):
374+
print(f' => copying {comp_name} from {comp_path}')
375+
do_copy_folder(src_path, dst_path)
376+
else:
377+
print(f"Warning: Component path not found: {src_path}")
378+
else:
379+
print(f"Note: Skipping system feature: {comp_name}")
380+
381+
return enabled_components
382+
174383
def MkDist(program, BSP_ROOT, RTT_ROOT, Env, project_name, project_path):
175384
print('make distribution....')
176385

@@ -191,10 +400,10 @@ def MkDist(program, BSP_ROOT, RTT_ROOT, Env, project_name, project_path):
191400
dist_handle = Env['dist_handle']
192401
dist_handle(BSP_ROOT, dist_dir)
193402

194-
# copy tools directory
195-
print('=> components')
196-
do_copy_folder(os.path.join(RTT_ROOT, 'components'), os.path.join(rtt_dir_path, 'components'))
197-
403+
# 使用新的组件复制函数并获取启用的组件列表
404+
config_file = os.path.join(BSP_ROOT, '.config')
405+
enabled_components = components_copy_files(RTT_ROOT, rtt_dir_path, config_file)
406+
198407
# skip documentation directory
199408
# skip examples
200409

@@ -247,4 +456,7 @@ def MkDist(program, BSP_ROOT, RTT_ROOT, Env, project_name, project_path):
247456
if project_path == None:
248457
zip_dist(dist_dir, project_name)
249458

459+
# 生成说明文档
460+
generate_dist_doc(dist_dir, enabled_components, project_name+'-dist', BSP_ROOT, RTT_ROOT)
461+
250462
print('dist project successfully!')

0 commit comments

Comments
 (0)