Improved build system generator for Python C/C++/Fortran/Cython extensions
—
Platform-specific functionality for CMake generator detection, selection, and platform-specific build configuration. Provides abstractions for cross-platform building and platform-specific optimizations.
Function for automatically detecting the current platform and returning appropriate platform-specific functionality.
def get_platform():
"""
Get an instance of CMakePlatform matching the current platform.
Automatically detects the current operating system and architecture
to return the appropriate platform-specific CMake integration.
Returns:
CMakePlatform: Platform-specific instance (WindowsPlatform, LinuxPlatform,
OSXPlatform, etc.)
"""Class representing a CMake generator with its configuration, environment variables, and platform-specific settings.
class CMakeGenerator:
"""
Represents a CMake generator configuration.
Encapsulates generator name, environment variables, toolset specification,
architecture targeting, and additional arguments for platform-specific
CMake generation.
"""
def __init__(
self,
name: str,
env: Mapping[str, str] | None = None,
toolset: str | None = None,
arch: str | None = None,
args: Iterable[str] | None = None,
) -> None:
"""
Initialize CMake generator with configuration.
Parameters:
- name: CMake generator name (e.g., "Visual Studio 16 2019", "Unix Makefiles")
- env: Environment variables to set during generation
- toolset: Toolset specification for generators that support it
- arch: Architecture specification (x64, Win32, ARM, etc.)
- args: Additional arguments to pass to generator
"""Abstract base class providing common platform functionality and generator management.
class CMakePlatform:
"""
Base class for platform-specific CMake integration.
Encapsulates platform-specific logic for CMake generator detection,
validation, and selection. Provides methods for testing generator
compatibility and finding the best available generator.
"""
def __init__(self) -> None:
"""Initialize platform with default configuration."""
@property
def default_generators(self) -> list[CMakeGenerator]:
"""
List of generators considered for automatic selection.
Returns:
List of CMakeGenerator objects in priority order
"""
@property
def generator_installation_help(self) -> str:
"""
Return message guiding user for installing valid toolchain.
Provides platform-specific instructions for installing build
tools and CMake generators.
Returns:
Help message string with installation instructions
"""
def get_best_generator(
self,
generator_name: str | None = None,
skip_generator_test: bool = False,
languages: Iterable[str] = ("CXX", "C"),
cleanup: bool = True,
cmake_executable: str = CMAKE_DEFAULT_EXECUTABLE,
cmake_args: Iterable[str] = (),
architecture: str | None = None,
) -> CMakeGenerator:
"""
Find working generator by testing configuration and compilation.
Tests generators in priority order to find one that successfully
configures and compiles a test project with the specified languages.
Parameters:
- generator_name: Specific generator to test (None for auto-selection)
- skip_generator_test: Skip compilation test (configuration only)
- languages: Programming languages to test (C, CXX, Fortran)
- cleanup: Clean up test directory after testing
- cmake_executable: Path to cmake executable
- cmake_args: Additional CMake arguments for testing
- architecture: Target architecture override
Returns:
CMakeGenerator object for working generator
Raises:
SKBuildGeneratorNotFoundError: If no working generator found
"""
def get_generator(self, generator_name: str) -> CMakeGenerator:
"""
Get generator by name from default generators list.
Parameters:
- generator_name: Name of generator to find
Returns:
CMakeGenerator object matching the name
"""
def get_generators(self, generator_name: str) -> list[CMakeGenerator]:
"""
Get all generators matching the given name.
Parameters:
- generator_name: Name pattern to match
Returns:
List of CMakeGenerator objects matching the name
"""Static methods for managing test projects used in generator validation.
@staticmethod
def write_test_cmakelist(languages: Iterable[str]) -> None:
"""
Write minimal CMakeLists.txt for testing language support.
Creates a test CMake project that validates support for the
specified programming languages.
Parameters:
- languages: Programming languages to test (C, CXX, Fortran, etc.)
"""
@staticmethod
def cleanup_test() -> None:
"""
Delete test project directory.
Removes temporary files and directories created during
generator testing and validation.
"""from skbuild.platform_specifics import get_platform
# Get current platform instance
platform = get_platform()
print(f"Platform: {type(platform).__name__}")
# Get available generators
generators = platform.default_generators
for gen in generators:
print(f"Available generator: {gen.name}")from skbuild.platform_specifics import get_platform, CMakeGenerator
platform = get_platform()
# Automatic generator selection
try:
best_gen = platform.get_best_generator(
languages=["C", "CXX"],
skip_generator_test=False
)
print(f"Selected generator: {best_gen.name}")
except SKBuildGeneratorNotFoundError:
print("No suitable generator found")
print(platform.generator_installation_help)
# Manual generator selection
try:
specific_gen = platform.get_generator("Unix Makefiles")
print(f"Found generator: {specific_gen.name}")
except:
print("Unix Makefiles not available on this platform")from skbuild.platform_specifics import CMakeGenerator
# Create custom generator with specific configuration
custom_gen = CMakeGenerator(
name="Visual Studio 16 2019",
env={"CC": "cl.exe", "CXX": "cl.exe"},
toolset="v142",
arch="x64",
args=["-T", "host=x64"]
)
# Use in platform selection
platform = get_platform()
try:
best_gen = platform.get_best_generator(
generator_name=custom_gen.name,
architecture="x64"
)
print(f"Using custom generator: {best_gen.name}")
except SKBuildGeneratorNotFoundError as e:
print(f"Custom generator failed: {e}")from skbuild.platform_specifics import get_platform
import sys
platform = get_platform()
# Platform-specific generator preferences
if sys.platform == "win32":
preferred_generators = ["Visual Studio 16 2019", "Visual Studio 15 2017"]
elif sys.platform == "darwin":
preferred_generators = ["Xcode", "Unix Makefiles"]
else:
preferred_generators = ["Unix Makefiles", "Ninja"]
# Try generators in preference order
selected_generator = None
for gen_name in preferred_generators:
try:
generator = platform.get_best_generator(
generator_name=gen_name,
skip_generator_test=True # Quick check
)
selected_generator = generator
break
except SKBuildGeneratorNotFoundError:
continue
if selected_generator:
print(f"Using generator: {selected_generator.name}")
else:
print("No preferred generators available")
print(platform.generator_installation_help)from skbuild.platform_specifics import get_platform, CMakePlatform
platform = get_platform()
# Test generator with specific languages
test_languages = ["C", "CXX", "Fortran"]
try:
# Write test project
CMakePlatform.write_test_cmakelist(test_languages)
# Test generator
working_gen = platform.get_best_generator(
languages=test_languages,
cleanup=False # Keep test files for inspection
)
print(f"Generator {working_gen.name} supports: {', '.join(test_languages)}")
finally:
# Always cleanup
CMakePlatform.cleanup_test()Install with Tessl CLI
npx tessl i tessl/pypi-scikit-build