Maison >développement back-end >C++ >Comment intégrer CMake dans setup.py pour créer des extensions Python ?
Création d'extensions Python et nécessité de CMake
Quand développant des extensions Python qui intègrent des bibliothèques C, CMake fournit un outil complet pour gérer les processus de construction. Cependant, le flux de travail typique implique la compilation manuelle des bibliothèques avec CMake avant d'exécuter setup.py bdist_wheel. Cela peut être gênant et prendre du temps.
Invoquer CMake dans setup.py
Pour résoudre ce problème, il est possible d'incorporer CMake dans le processus de construction setup.py . La clé est de créer une commande build_ext personnalisée qui utilise CMake pour configurer et créer les extensions.
Personnalisation de la commande build_ext
Dans le fichier setup.py, remplacez le classe de commande build_ext et enregistrez-la dans les classes de commandes. Dans votre implémentation personnalisée, configurez et invoquez CMake pour créer les modules d'extension.
Exemple de projet et de script de configuration
Pour démontrer le concept, considérez un projet simple avec un C extension (foo) et un module Python (spam.eggs). Le script setup.py exploite une classe CMakeExtension qui encapsule l'extension sans appeler le build_ext d'origine. La méthode build_cmake gère la configuration et les étapes de construction de CMake.
<code class="python">import os import pathlib from setuptools import setup, Extension from setuptools.command.build_ext import build_ext_orig class CMakeExtension(Extension): def __init__(self, name): # don't invoke the original build_ext for this special extension super().__init__(name, sources=[]) class build_ext(build_ext_orig): def run(self): for ext in self.extensions: self.build_cmake(ext) super().run() def build_cmake(self, ext): cwd = pathlib.Path().absolute() # these dirs will be created in build_py, so if you don't have # any python sources to bundle, the dirs will be missing build_temp = pathlib.Path(self.build_temp) build_temp.mkdir(parents=True, exist_ok=True) extdir = pathlib.Path(self.get_ext_fullpath(ext.name)) extdir.mkdir(parents=True, exist_ok=True) # example of cmake args config = 'Debug' if self.debug else 'Release' cmake_args = [ '-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=' + str(extdir.parent.absolute()), '-DCMAKE_BUILD_TYPE=' + config ] # example of build args build_args = [ '--config', config, '--', '-j4' ] os.chdir(str(build_temp)) self.spawn(['cmake', str(cwd)] + cmake_args) if not self.dry_run: self.spawn(['cmake', '--build', '.'] + build_args) setup( name='spam', version='0.1', packages=['spam'], ext_modules=[CMakeExtension('spam/foo')], cmdclass={ 'build_ext': build_ext, } )</code>
Test et validation
En construisant la roue du projet et en l'installant, vous pouvez vérifier si la bibliothèque est installé avec succès et fonctionnel. L'exécution d'une fonction wrapper à partir du module spam.eggs devrait produire le résultat attendu.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!