# 3. Construire les extensions C et C++ avec distutils

Starting in Python 1.4, Python provides, on Unix, a special make file for building make files for building dynamically-linked extensions and custom interpreters. Starting with Python 2.0, this mechanism (known as related to Makefile.pre.in, and Setup files) is no longer supported. Building custom interpreters was rarely used, and extension modules can be built using distutils.

Building an extension module using distutils requires that distutils is installed on the build machine, which is included in Python 2.x and available separately for Python 1.5. Since distutils also supports creation of binary packages, users don’t necessarily need a compiler and distutils to install the extension.

Un paquet distutils contient un script `setup.py`. C’est un simple fichier Python, ressemblant dans la plupart des cas à :

    from distutils.core import setup, Extension

    module1 = Extension('demo',
                        sources = ['demo.c'])

    setup (name = 'PackageName',
           version = '1.0',
           description = 'This is a demo package',
           ext_modules = [module1])

Avec ce `setup.py` et un fichier `demo.c`, lancer :

    python setup.py build

compilera `demo.c`, et produira un module d’extension nommé `demo` dans le dossier `build`. En fonction du système, le fichier du module peut se retrouver dans `build/lib.system`, et son nom peut être `demo.py` ou `demo.pyd`.

Dans le fichier `setup.py`, tout est exécuté en appelant la fonction `setup`. Elle prend une quantité variable d’arguments nommés, l’exemple précédent n’en utilisant qu’une partie. L’exemple précise des méta-informations pour construire les paquets, et définir le contenu du paquet. Normalement un paquet contient des modules additionnels, comme des modules sources, documentation, sous paquets, etc. Referez-vous à la documentation de distutils dans Distribuer des modules Python (Version historique) pour en apprendre plus sur les fonctionnalités de distutils. Cette section n’explique que la construction de modules d’extension.

Il est classique de pré-construire les arguments de `setup()`, pour mieux structurer le script pilote. Dans l’exemple précédent, l’argument `ext_modules` donné à `setup()` est une liste de modules d’extension, dont chacun est une instance de `Extension`. Dans l’exemple, l’instance défini une extension nommée `demo` qui est construite en compilant un seul fichier source, `demo.c`.

Dans la plupart des cas, construire une extension est plus complexe à cause des bibliothèques et définitions de préprocesseurs dont la compilation pourrait dépendre. C’est ce qu’on remarque dans l’exemple plus bas.

    from distutils.core import setup, Extension

    module1 = Extension('demo',
                        define_macros = [('MAJOR_VERSION', '1'),
                                         ('MINOR_VERSION', '0')],
                        include_dirs = ['/usr/local/include'],
                        libraries = ['tcl83'],
                        library_dirs = ['/usr/local/lib'],
                        sources = ['demo.c'])

    setup (name = 'PackageName',
           version = '1.0',
           description = 'This is a demo package',
           author = 'Martin v. Loewis',
           author_email = 'martin@v.loewis.de',
           url = 'https://docs.python.org/extending/building',
           long_description = '''
    This is really just a demo package.
    ''',
           ext_modules = [module1])

Dans cet exemple, `setup()` est appelée avec des méta-informations supplémentaires, ce qui est recommandé lorsque le paquet est amené à être distribué. Pour l’extension elle même, elle donne des variables de préprocesseur (defines), dossiers de bibliothèques, et bibliothèques. En fonction du compilateur distutils peut lui donner ces informations de différentes manières, par exemple, sur Linux, on pourrait obtenir cette ligne :

    gcc -DNDEBUG -g -O3 -Wall -Wstrict-prototypes -fPIC -DMAJOR_VERSION=1 -DMINOR_VERSION=0 -I/usr/local/include -I/usr/local/include/python2.2 -c demo.c -o build/temp.linux-i686-2.2/demo.o

    gcc -shared build/temp.linux-i686-2.2/demo.o -L/usr/local/lib -ltcl83 -o build/lib.linux-i686-2.2/demo.so

Ces lignes ne sont qu’à titre d’exemple, les utilisateurs de distutils doivent avoir confiance en distutils qui fera les appels correctement.

## 3.1. Distribuer vos modules d’extension

Lorsqu’une extension a été construite avec succès, il existe trois moyens de l’utiliser.

Typiquement, les utilisateurs vont vouloir installer le module, ils le font en exécutant :

    python setup.py install

Les mainteneurs de modules voudront produire des paquets source, pour ce faire ils exécuteront :

    python setup.py sdist

Dans certains cas, des fichiers supplémentaires doivent être joints à la distribution source, c’est possible grâce à un fichier `MANIFEST.in`. Voir la documentation de distutils pour plus de détails.

Si la distribution source a été construite avec succès, les mainteneurs peuvent créer une distribution binaire. En fonction de la plateforme, une des commandes suivantes peut être utilisée.

    python setup.py bdist_wininst
    python setup.py bdist_rpm
    python setup.py bdist_dumb