Search code examples
pythonpython-c-apipython-poetry

How to build C extensions via poetry?


To build a python project managed with poetry I need to build C extensions first (an equivalent to python setup.py build). poetry is able to do this according to this github issue. But to me it's not clear what to include into pyproject.toml that the C extension build is executed when building with poetry build?


Solution

  • Add build.py to the repo-root. E.g. if one has one header file directory and 2 source files:

    from distutils.command.build_ext import build_ext
    
    
    ext_modules = [
        Extension("<module-path-imported-into-python>",
                  include_dirs=["<header-file-directory>"],
                  sources=["<source-file-0>", "<source-file-1>"],
                 ),
    ]
    
    
    class BuildFailed(Exception):
        pass
    
    
    class ExtBuilder(build_ext):
    
        def run(self):
            try:
                build_ext.run(self)
            except (DistutilsPlatformError, FileNotFoundError):
                raise BuildFailed('File not found. Could not compile C extension.')
    
        def build_extension(self, ext):
            try:
                build_ext.build_extension(self, ext)
            except (CCompilerError, DistutilsExecError, DistutilsPlatformError, ValueError):
                raise BuildFailed('Could not compile C extension.')
    
    
    def build(setup_kwargs):
        """
        This function is mandatory in order to build the extensions.
        """
        setup_kwargs.update(
            {"ext_modules": ext_modules, "cmdclass": {"build_ext": ExtBuilder}}
        )
    

    Add to pyproject.toml:

    [tool.poetry]
    build = "build.py"
    

    To build the extension execute poetry build.

    For an example refer to this PR.