I have written a c extension package using CFFI and I am trying to work out how to build it with setuptools. My package looks like this:
pkgName/
pyproject.toml
setup.py
src/
pkgName/
build_cffi.py # Compiles C extension with CFFI
mainCfile.C
mainCfile.h
other.h
wrapper.py
__init__.py
My build_cffi.py looks like this:
ffibuilder.set_source(
"c_binding",
"""
#include "mainCfile.h" // the C header of the library
""",
sources=['mainCfile.c'], include_dirs = [os.path.dirname(os.path.realpath(__file__))]
)
ffibuilder.cdef(
"""
void test_print(int to_print);
"""
)
if __name__ == "__main__":
ffibuilder.compile(verbose=True)
and my setup.py looks like this
from setuptools import setup
setup(
setup_requires=["cffi>=1.0.0"],
cffi_modules=["src/pkgName/build_cffi.py:ffibuilder"],
install_requires=["cffi>=1.0.0"],
)
Now, when I run build_cffi.py on its own from the src/pkgName folder, it builds fine. However when I run python3 -m build from the package root directory, the compilation fails with this error:
fatal error: mainCfile.h: No such file or directory
How can I get CFFI and setuptools to find my directory with the c headers from setuptools? I have tried to add this include_dirs = [os.path.dirname(os.path.realpath(__file__))]) but it made no difference.
Edit: Found solution
The .c and .h files need to be added by setuptools to the source distribution. This can be done in a manifest.in file, however you can do this in setup.py by adding this extra line to the setup() function:
package_data={"": ["*.h", "*.c"]}.
I also had to make this change to the build_cffi.py file:
ffibuilder.set_source(
"pkgName.c_bindings", <- Changed to pkg.file
"""
#include "mainCfile.h"
""",
sources=["src/pkgName/mainCfile.c"], # <-- Make relative to root directory
include_dirs=[os.path.dirname(os.path.realpath(__file__))],
)