88
99import argparse
1010import os
11+ import shutil
1112import sys
1213import typing as t
14+ from pathlib import Path
1315
1416from idf_component_manager .core import ComponentManager
1517from idf_component_tools import error , setup_logging , warn
@@ -23,19 +25,50 @@ def _component_list_file(build_dir):
2325 return os .path .join (build_dir , 'components_with_manifests_list.temp' )
2426
2527
28+ def _get_ppid_file_path (local_component_list_file : t .Optional [str ]) -> Path :
29+ return Path (f'{ local_component_list_file } .{ os .getppid ()} ' )
30+
31+
32+ def _get_component_list_file (local_components_list_file ):
33+ """
34+ Get the appropriate component list file, preferring the PPID version
35+ if it exists from a parent CMake run.
36+
37+ Args:
38+ args: Command line arguments containing local_components_list_file
39+
40+ Returns:
41+ Path to the component list file to use, or None if not configured
42+ """
43+ if not local_components_list_file :
44+ return None
45+
46+ component_list_parent_pid = _get_ppid_file_path (local_components_list_file )
47+ # Always use local component list file from the first execution of the component manager
48+ # (component_list_parent_pid) during one CMake run,
49+ # to be sure that it doesn't contain components introduced by the component manager.
50+ if component_list_parent_pid .exists ():
51+ return component_list_parent_pid
52+ else :
53+ return local_components_list_file
54+
55+
2656def prepare_dep_dirs (args ):
2757 if args .sdkconfig_json_file :
2858 KCONFIG_CONTEXT .get ().update_from_file (args .sdkconfig_json_file )
2959
3060 build_dir = args .build_dir or os .path .dirname (args .managed_components_list_file )
61+
62+ local_components_list_file = _get_component_list_file (args .local_components_list_file )
63+
3164 ComponentManager (
3265 args .project_dir ,
3366 lock_path = args .lock_path ,
3467 interface_version = args .interface_version ,
3568 ).prepare_dep_dirs (
3669 managed_components_list_file = args .managed_components_list_file ,
3770 component_list_file = _component_list_file (build_dir ),
38- local_components_list_file = args . local_components_list_file ,
71+ local_components_list_file = local_components_list_file ,
3972 )
4073
4174 kconfig_ctx = KCONFIG_CONTEXT .get ()
@@ -67,7 +100,26 @@ def debug_message(req: ComponentRequirement) -> str:
67100 f'but not found in any Kconfig file:\n '
68101 f'{ _nl .join (sorted (debug_strs ))} \n '
69102 )
70- exit (10 )
103+
104+ # Copy local component list file for next run of CMake before exiting
105+ if args .local_components_list_file :
106+ ppid_file = _get_ppid_file_path (args .local_components_list_file )
107+
108+ if not Path (ppid_file ).exists ():
109+ try :
110+ shutil .copyfile (args .local_components_list_file , ppid_file )
111+ except (OSError , IOError ) as e :
112+ raise FatalError (
113+ f"Failed to copy '{ args .local_components_list_file } ' → '{ ppid_file } ': { e } "
114+ ) from e
115+ # Exiting with code 10 to signal CMake to re-run component discovery due to missing KConfig options
116+ sys .exit (10 )
117+
118+ # Clean up PPID file on successful completion
119+ if args .local_components_list_file :
120+ ppid_file_path = Path (_get_ppid_file_path (args .local_components_list_file ))
121+ if ppid_file_path .exists ():
122+ ppid_file_path .unlink ()
71123
72124
73125def inject_requirements (args ):
0 commit comments