cppython
Advanced tools
| """Builder to help resolve cmake state""" | ||
| import logging | ||
| import os | ||
| import shutil | ||
| from pathlib import Path | ||
@@ -11,2 +13,49 @@ from typing import Any | ||
| def _resolve_cmake_binary(configured_path: Path | None) -> Path | None: | ||
| """Resolve the cmake binary path with validation. | ||
| Resolution order: | ||
| 1. CMAKE_BINARY environment variable (highest priority) | ||
| 2. Configured path from cmake_binary setting | ||
| 3. cmake from PATH (fallback) | ||
| If a path is specified (via env or config) but doesn't exist, | ||
| a warning is logged and we fall back to PATH lookup. | ||
| Args: | ||
| configured_path: The cmake_binary path from configuration, if any | ||
| Returns: | ||
| Resolved cmake path, or None if not found anywhere | ||
| """ | ||
| logger = logging.getLogger('cppython.cmake') | ||
| # Environment variable takes precedence | ||
| if env_binary := os.environ.get('CMAKE_BINARY'): | ||
| env_path = Path(env_binary) | ||
| if env_path.exists(): | ||
| return env_path | ||
| logger.warning( | ||
| 'CMAKE_BINARY environment variable points to non-existent path: %s. ' | ||
| 'Falling back to PATH lookup.', | ||
| env_binary, | ||
| ) | ||
| # Try configured path | ||
| if configured_path: | ||
| if configured_path.exists(): | ||
| return configured_path | ||
| logger.warning( | ||
| 'Configured cmake_binary path does not exist: %s. ' | ||
| 'Falling back to PATH lookup.', | ||
| configured_path, | ||
| ) | ||
| # Fall back to PATH lookup | ||
| if cmake_in_path := shutil.which('cmake'): | ||
| return Path(cmake_in_path) | ||
| return None | ||
| def resolve_cmake_data(data: dict[str, Any], core_data: CorePluginData) -> CMakeData: | ||
@@ -31,7 +80,3 @@ """Resolves the input data table from defaults to requirements | ||
| # Resolve cmake binary: environment variable takes precedence over configuration | ||
| cmake_binary: Path | None = None | ||
| if env_binary := os.environ.get('CMAKE_BINARY'): | ||
| cmake_binary = Path(env_binary) | ||
| elif parsed_data.cmake_binary: | ||
| cmake_binary = parsed_data.cmake_binary | ||
| cmake_binary = _resolve_cmake_binary(parsed_data.cmake_binary) | ||
@@ -38,0 +83,0 @@ return CMakeData( |
@@ -9,3 +9,2 @@ """Conan Provider Plugin | ||
| import os | ||
| import shutil | ||
| from logging import Logger, getLogger | ||
@@ -246,19 +245,2 @@ from pathlib import Path | ||
| @staticmethod | ||
| def _resolve_cmake_binary(cmake_path: Path | str | None) -> str | None: | ||
| """Resolve the cmake binary path. | ||
| If an explicit path is provided, use it. Otherwise, try to find cmake | ||
| in the current Python environment (venv) to ensure we use the same | ||
| cmake version for all operations including dependency builds. | ||
| Args: | ||
| cmake_path: Explicit cmake path, or None to auto-detect | ||
| Returns: | ||
| Resolved cmake path as string, or None if not found | ||
| """ | ||
| resolved = cmake_path or shutil.which('cmake') | ||
| return str(Path(resolved).resolve()) if resolved else None | ||
| def _sync_with_cmake(self, consumer: SyncConsumer) -> CMakeSyncData: | ||
@@ -274,4 +256,5 @@ """Synchronize with CMake generator and create sync data. | ||
| # Extract cmake_binary from CMakeGenerator if available | ||
| if isinstance(consumer, CMakeGenerator) and not os.environ.get('CMAKE_BINARY'): | ||
| self._cmake_binary = self._resolve_cmake_binary(consumer.data.cmake_binary) | ||
| # The cmake_binary is already validated and resolved during CMake data resolution | ||
| if isinstance(consumer, CMakeGenerator) and consumer.data.cmake_binary: | ||
| self._cmake_binary = str(consumer.data.cmake_binary.resolve()) | ||
@@ -306,3 +289,7 @@ return self._create_cmake_sync_data() | ||
| def publish(self) -> None: | ||
| """Publishes the package using conan create workflow.""" | ||
| """Publishes the package using conan create workflow. | ||
| Creates packages for all configured build types (e.g., Release, Debug) | ||
| to support both single-config and multi-config generators. | ||
| """ | ||
| project_root = self.core_data.project_data.project_root | ||
@@ -316,28 +303,9 @@ conanfile_path = project_root / 'conanfile.py' | ||
| try: | ||
| # Build conan create command arguments | ||
| command_args = ['create', str(conanfile_path)] | ||
| # Create packages for each configured build type | ||
| build_types = self.data.build_types | ||
| for build_type in build_types: | ||
| logger.info('Creating package for build type: %s', build_type) | ||
| self._run_conan_create(conanfile_path, build_type, logger) | ||
| # Add build mode (build everything for publishing) | ||
| command_args.extend(['--build', 'missing']) | ||
| # Skip test dependencies during publishing | ||
| command_args.extend(['-c', 'tools.graph:skip_test=True']) | ||
| command_args.extend(['-c', 'tools.build:skip_test=True']) | ||
| # Add cmake binary configuration if specified | ||
| if self._cmake_binary: | ||
| # Quote the path if it contains spaces | ||
| cmake_path = f'"{self._cmake_binary}"' if ' ' in self._cmake_binary else self._cmake_binary | ||
| command_args.extend(['-c', f'tools.cmake:cmake_program={cmake_path}']) | ||
| # Run conan create using reusable Conan API instance | ||
| # Change to project directory since Conan API might not handle cwd like subprocess | ||
| original_cwd = os.getcwd() | ||
| try: | ||
| os.chdir(str(project_root)) | ||
| self._conan_api.command.run(command_args) | ||
| finally: | ||
| os.chdir(original_cwd) | ||
| # Upload if not skipped | ||
| # Upload once after all configurations are built | ||
| if not self.data.skip_upload: | ||
@@ -351,2 +319,38 @@ self._upload_package(logger) | ||
| def _run_conan_create(self, conanfile_path: Path, build_type: str, logger: Logger) -> None: | ||
| """Run conan create command for a specific build type. | ||
| Args: | ||
| conanfile_path: Path to the conanfile.py | ||
| build_type: Build type (Release, Debug, etc.) | ||
| logger: Logger instance | ||
| """ | ||
| # Build conan create command arguments | ||
| command_args = ['create', str(conanfile_path)] | ||
| # Add build mode (build everything for publishing) | ||
| command_args.extend(['--build', 'missing']) | ||
| # Skip test dependencies during publishing | ||
| command_args.extend(['-c', 'tools.graph:skip_test=True']) | ||
| command_args.extend(['-c', 'tools.build:skip_test=True']) | ||
| # Add build type setting | ||
| command_args.extend(['-s', f'build_type={build_type}']) | ||
| # Add cmake binary configuration if specified | ||
| if self._cmake_binary: | ||
| # Quote the path if it contains spaces | ||
| cmake_path = f'"{self._cmake_binary}"' if ' ' in self._cmake_binary else self._cmake_binary | ||
| command_args.extend(['-c', f'tools.cmake:cmake_program={cmake_path}']) | ||
| # Run conan create using reusable Conan API instance | ||
| # Change to project directory since Conan API might not handle cwd like subprocess | ||
| original_cwd = os.getcwd() | ||
| try: | ||
| os.chdir(str(self.core_data.project_data.project_root)) | ||
| self._conan_api.command.run(command_args) | ||
| finally: | ||
| os.chdir(original_cwd) | ||
| def _upload_package(self, logger) -> None: | ||
@@ -353,0 +357,0 @@ """Upload the package to configured remotes using Conan API.""" |
+1
-1
| Metadata-Version: 2.1 | ||
| Name: cppython | ||
| Version: 0.9.15.dev1 | ||
| Version: 0.9.15.dev3 | ||
| Summary: A Python management solution for C++ dependencies | ||
@@ -5,0 +5,0 @@ Author-Email: Synodic Software <contact@synodic.software> |
+1
-1
@@ -18,3 +18,3 @@ [project] | ||
| ] | ||
| version = "0.9.15.dev1" | ||
| version = "0.9.15.dev3" | ||
@@ -21,0 +21,0 @@ [project.license] |
Alert delta unavailable
Currently unable to show alert delta for PyPI packages.
343063
0.48%7570
0.52%