@@ -172,36 +172,6 @@ def zip_dist(dist_dir, dist_name):
172172
173173 zip .close ()
174174
175- def get_system_features ():
176- """Get system built-in feature list"""
177- return {
178- # Kernel features
179- 'components_init' ,
180- 'console' ,
181- 'cpu_usage_tracer' ,
182- 'heap' ,
183- 'slab' ,
184- 'mempool' ,
185- 'memtrace' ,
186- 'timer_soft' ,
187- 'event' ,
188- 'mailbox' ,
189- 'messagequeue' ,
190- 'mutex' ,
191- 'semaphore' ,
192- 'signals' ,
193- 'hook' ,
194- 'idle_hook' ,
195- 'thread' ,
196- 'cache' ,
197- 'debug' ,
198- 'device_ops' ,
199- 'overflow_check' ,
200- 'slab_as_heap' ,
201- 'user_main' ,
202- 'stdc_atomic' ,
203- }
204-
205175def parse_components_from_config (config_file ):
206176 """Parse enabled components from .config file"""
207177 enabled_components = set ()
@@ -248,7 +218,11 @@ def parse_kconfig(kconfig_file):
248218
249219 def get_relative_path (full_path ):
250220 """Get path relative to RTT_ROOT"""
251- return os .path .relpath (os .path .dirname (full_path ), RTT_ROOT )
221+ rel_path = os .path .relpath (os .path .dirname (full_path ), RTT_ROOT )
222+ # Skip if path is directly under components directory
223+ if rel_path == 'components' or rel_path == os .path .join ('components' , '' ):
224+ return None
225+ return rel_path
252226
253227 # Scan all component directories
254228 for root , dirs , files in os .walk (components_root ):
@@ -257,9 +231,10 @@ def get_relative_path(full_path):
257231 component_configs = parse_kconfig (kconfig_path )
258232 rel_path = get_relative_path (kconfig_path )
259233
260- # Associate component names with paths
261- for comp_name in component_configs :
262- components_map [comp_name ] = rel_path
234+ # Only add component if it has a valid sub-path
235+ if rel_path :
236+ for comp_name in component_configs :
237+ components_map [comp_name ] = rel_path
263238
264239 return components_map
265240
@@ -359,10 +334,114 @@ def generate_dist_doc(dist_dir, enabled_components, project_name, BSP_ROOT, RTT_
359334
360335 print (f"=> Generated distribution documentation: { doc_file } " )
361336
337+ def is_text_file (filepath ):
338+ """Check if a file is a text file"""
339+ text_extensions = {
340+ '.h' , '.c' , '.cpp' , '.hpp' , '.S' , '.s' , '.asm' ,
341+ '.txt' , '.md' , '.rst' , '.ini' , '.conf' ,
342+ 'Kconfig' , 'SConscript' , 'SConstruct' ,
343+ '.json' , '.yml' , '.yaml' ,
344+ '.cmake' , 'CMakeLists.txt' ,
345+ '.py' , '.sh' , '.bat' ,
346+ 'README' , 'LICENSE' , 'Makefile'
347+ }
348+
349+ # Check by extension
350+ ext = os .path .splitext (filepath )[1 ].lower ()
351+ if ext in text_extensions or os .path .basename (filepath ) in text_extensions :
352+ return True
353+
354+ # Additional check for files without extension
355+ if '.' not in os .path .basename (filepath ):
356+ try :
357+ with open (filepath , 'r' , encoding = 'utf-8' ) as f :
358+ f .read (1024 ) # Try to read as text
359+ return True
360+ except :
361+ return False
362+
363+ return False
364+
365+ def copy_component_dependencies (src_path , dst_base , RTT_ROOT , copied_files = None ):
366+ """Copy component dependencies (text files) from parent directories"""
367+ if copied_files is None :
368+ copied_files = set ()
369+
370+ # Get relative path from RTT_ROOT
371+ rel_path = os .path .relpath (src_path , RTT_ROOT )
372+ parent_path = os .path .dirname (rel_path )
373+
374+ # Process all parent directories until RTT_ROOT
375+ while parent_path and parent_path != '.' :
376+ src_dir = os .path .join (RTT_ROOT , parent_path )
377+
378+ # Copy all text files in the directory (not recursively)
379+ for item in os .listdir (src_dir ):
380+ src_file = os .path .join (src_dir , item )
381+ if os .path .isfile (src_file ) and src_file not in copied_files :
382+ if is_text_file (src_file ):
383+ dst_file = os .path .join (dst_base , parent_path , item )
384+ dst_dir = os .path .dirname (dst_file )
385+
386+ if not os .path .exists (dst_dir ):
387+ os .makedirs (dst_dir )
388+
389+ do_copy_file (src_file , dst_file )
390+ copied_files .add (src_file )
391+ print (f' => copying { item } from { parent_path } ' )
392+
393+ parent_path = os .path .dirname (parent_path )
394+
395+ return copied_files
396+
397+ def get_essential_paths ():
398+ """Get essential paths that must be included"""
399+ return {
400+ 'components/libc/compilers' , # Common compiler support
401+ 'components/drivers/include' , # Driver headers
402+ 'components/drivers/core' , # Driver core
403+ 'components/utilities' , # Utility functions
404+ 'components/mm' , # Memory management
405+ 'components/legacy/ipc' , # IPC support, not always used, but have no config option for it
406+ }
407+
408+ def copy_essential_paths (RTT_ROOT , rtt_dir_path , copied_files = None ):
409+ """Copy essential paths and their build files"""
410+ if copied_files is None :
411+ copied_files = set ()
412+
413+ print ('=> copying essential paths' )
414+ for path in get_essential_paths ():
415+ src_path = os .path .join (RTT_ROOT , path )
416+ if os .path .exists (src_path ):
417+ dst_path = os .path .join (rtt_dir_path , path )
418+ print (f' => copying { path } ' )
419+ do_copy_folder (src_path , dst_path )
420+
421+ # Copy build files for this path
422+ copied_files = copy_component_dependencies (src_path , rtt_dir_path , RTT_ROOT , copied_files )
423+
424+ return copied_files
425+
362426def components_copy_files (RTT_ROOT , rtt_dir_path , config_file ):
363427 """Copy components based on configuration"""
364428 print ('=> components (selective copy)' )
365429
430+ # Track copied build files to avoid duplication
431+ copied_files = set ()
432+
433+ # Copy components/SConscript first
434+ components_sconscript = os .path .join (RTT_ROOT , 'components' , 'SConscript' )
435+ if os .path .exists (components_sconscript ):
436+ dst_dir = os .path .join (rtt_dir_path , 'components' )
437+ if not os .path .exists (dst_dir ):
438+ os .makedirs (dst_dir )
439+ do_copy_file (components_sconscript , os .path .join (dst_dir , 'SConscript' ))
440+ copied_files .add (components_sconscript )
441+
442+ # Copy essential paths first
443+ copied_files = copy_essential_paths (RTT_ROOT , rtt_dir_path , copied_files )
444+
366445 # Get enabled components
367446 enabled_components = parse_components_from_config (config_file )
368447 if not enabled_components :
@@ -375,9 +454,13 @@ def components_copy_files(RTT_ROOT, rtt_dir_path, config_file):
375454 if comp_path :
376455 src_path = os .path .join (RTT_ROOT , comp_path )
377456 dst_path = os .path .join (rtt_dir_path , comp_path )
457+
378458 if os .path .exists (src_path ):
379459 print (f' => copying { comp_name } from { comp_path } ' )
380460 do_copy_folder (src_path , dst_path )
461+
462+ # Copy parent directory build files
463+ copied_files = copy_component_dependencies (src_path , rtt_dir_path , RTT_ROOT , copied_files )
381464 else :
382465 print (f"Warning: Component path not found: { src_path } " )
383466 else :
0 commit comments