66"""
77
88import logging
9- import subprocess
109from pathlib import Path
1110from typing import Any
1211
@@ -72,7 +71,7 @@ def information() -> Information:
7271 return Information ()
7372
7473 def _install_dependencies (self , * , update : bool = False ) -> None :
75- """Install/update dependencies using conan CLI command .
74+ """Install/update dependencies using Conan API .
7675
7776 Args:
7877 update: If True, check remotes for newer versions/revisions and install those.
@@ -95,50 +94,85 @@ def _install_dependencies(self, *, update: bool = False) -> None:
9594 self .core_data .cppython_data .build_path .mkdir (parents = True , exist_ok = True )
9695 logger .debug ('Created build path: %s' , self .core_data .cppython_data .build_path )
9796
98- # Build conan install command
97+ # Initialize Conan API
98+ conan_api = ConanAPI ()
99+
100+ # Get project paths
99101 project_root = self .core_data .project_data .project_root
100102 conanfile_path = project_root / 'conanfile.py'
101103
102104 if not conanfile_path .exists ():
103105 raise ProviderInstallationError ('conan' , 'Generated conanfile.py not found' )
104106
105- # Prepare conan install command
106- cmd = [
107- 'conan' ,
108- 'install' ,
109- str (conanfile_path ),
110- '--output-folder' ,
111- str (self .core_data .cppython_data .build_path ),
112- '--build' ,
113- 'missing' ,
114- ]
115-
116- if update :
117- cmd .extend (['--update' ])
118-
119- logger .debug ('Running conan command: %s' , ' ' .join (cmd ))
120-
121- # Execute conan install command
122- result = subprocess .run (cmd , cwd = str (project_root ), capture_output = True , text = True , check = False )
123-
124- # Log output for debugging
125- if result .stdout :
126- logger .debug ('Conan stdout:\n %s' , result .stdout )
127- if result .stderr :
128- logger .debug ('Conan stderr:\n %s' , result .stderr )
129-
130- # Check for success
131- if result .returncode != 0 :
132- error_msg = f'Conan install failed with return code { result .returncode } '
133- if result .stderr :
134- error_msg += f': { result .stderr } '
135- raise ProviderInstallationError ('conan' , error_msg )
136-
137- logger .debug ('Successfully installed dependencies using conan CLI' )
138-
139- except subprocess .SubprocessError as e :
140- operation = 'update' if update else 'install'
141- raise ProviderInstallationError ('conan' , f'Failed to { operation } dependencies: { e } ' , e ) from e
107+ # Get all remotes
108+ all_remotes = conan_api .remotes .list ()
109+ logger .debug ('Available remotes: %s' , [remote .name for remote in all_remotes ])
110+
111+ # Get default profiles, handle case when no default profile exists
112+ try :
113+ profile_host_path = conan_api .profiles .get_default_host ()
114+ profile_build_path = conan_api .profiles .get_default_build ()
115+
116+ # Ensure we have valid profile paths
117+ if profile_host_path is None :
118+ # Create a minimal default profile if none exists
119+ profile_host = conan_api .profiles .get_profile ([])
120+ else :
121+ profile_host = conan_api .profiles .get_profile ([profile_host_path ])
122+
123+ if profile_build_path is None :
124+ # Create a minimal default profile if none exists
125+ profile_build = conan_api .profiles .get_profile ([])
126+ else :
127+ profile_build = conan_api .profiles .get_profile ([profile_build_path ])
128+
129+ except Exception :
130+ # If profile operations fail, create minimal default profiles
131+ profile_host = conan_api .profiles .get_profile ([])
132+ profile_build = conan_api .profiles .get_profile ([])
133+
134+ logger .debug ('Using profiles: host=%s, build=%s' , profile_host , profile_build )
135+
136+ # Build dependency graph
137+ deps_graph = conan_api .graph .load_graph_consumer (
138+ path = str (conanfile_path ),
139+ name = None ,
140+ version = None ,
141+ user = None ,
142+ channel = None ,
143+ profile_host = profile_host ,
144+ profile_build = profile_build ,
145+ lockfile = None ,
146+ remotes = all_remotes ,
147+ update = None if not update else True ,
148+ check_updates = update ,
149+ is_build_require = False ,
150+ )
151+
152+ logger .debug ('Dependency graph loaded with %d nodes' , len (deps_graph .nodes ))
153+
154+ # Analyze binaries to determine what needs to be built/downloaded
155+ conan_api .graph .analyze_binaries (
156+ graph = deps_graph ,
157+ build_mode = ['missing' ], # Only build what's missing
158+ remotes = all_remotes ,
159+ update = None if not update else True ,
160+ lockfile = None ,
161+ )
162+
163+ # Install all dependencies
164+ conan_api .install .install_binaries (deps_graph = deps_graph , remotes = all_remotes )
165+
166+ # Generate files for the consumer (conandata.yml, conan_toolchain.cmake, etc.)
167+ conan_api .install .install_consumer (
168+ deps_graph = deps_graph ,
169+ generators = ['CMakeToolchain' , 'CMakeDeps' ],
170+ source_folder = str (project_root ),
171+ output_folder = str (self .core_data .cppython_data .build_path ),
172+ )
173+
174+ logger .debug ('Successfully installed dependencies using Conan API' )
175+
142176 except Exception as e :
143177 operation = 'update' if update else 'install'
144178 error_msg = str (e )
@@ -232,11 +266,28 @@ def publish(self) -> None:
232266 remotes = all_remotes , # Use all remotes for dependency resolution during export
233267 )
234268
235- # Step 2: Get default profiles
236- profile_host_path = conan_api .profiles .get_default_host ()
237- profile_build_path = conan_api .profiles .get_default_build ()
238- profile_host = conan_api .profiles .get_profile ([profile_host_path ])
239- profile_build = conan_api .profiles .get_profile ([profile_build_path ])
269+ # Step 2: Get default profiles, handle case when no default profile exists
270+ try :
271+ profile_host_path = conan_api .profiles .get_default_host ()
272+ profile_build_path = conan_api .profiles .get_default_build ()
273+
274+ # Ensure we have valid profile paths
275+ if profile_host_path is None :
276+ # Create a minimal default profile if none exists
277+ profile_host = conan_api .profiles .get_profile ([])
278+ else :
279+ profile_host = conan_api .profiles .get_profile ([profile_host_path ])
280+
281+ if profile_build_path is None :
282+ # Create a minimal default profile if none exists
283+ profile_build = conan_api .profiles .get_profile ([])
284+ else :
285+ profile_build = conan_api .profiles .get_profile ([profile_build_path ])
286+
287+ except Exception :
288+ # If profile operations fail, create minimal default profiles
289+ profile_host = conan_api .profiles .get_profile ([])
290+ profile_build = conan_api .profiles .get_profile ([])
240291
241292 # Step 3: Build dependency graph for the package
242293 deps_graph = conan_api .graph .load_graph_consumer (
0 commit comments