Maison >développement back-end >C++ >Comment intégrer CMake dans setup.py pour créer des extensions Python ?

Comment intégrer CMake dans setup.py pour créer des extensions Python ?

Susan Sarandon
Susan Sarandonoriginal
2024-10-27 12:11:02804parcourir

How to Integrate CMake into setup.py for Building Python Extensions?

Comment intégrer CMake dans setup.py pour l'extension setuptools

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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn