Place Pre-compiled Extensions In Root Folder Of Non-pure Python Wheel Package
TL;DR How do you get distutils/setuptools to include a non-pure data file correctly? I've got a project that does some non-trivial code generation using a custom toolchain, and the
Solution 1:
This works. distutils
and setuptools
have to be some of the worst designed pieces of central Python infrastructure that exist.
from setuptools import setup, find_packages, Extension
from setuptools.command.build_ext import build_ext
import os
import pathlib
import shutil
suffix = '.pyd' if os.name == 'nt' else '.so'
class CustomDistribution(Distribution):
def iter_distribution_names(self):
for pkg in self.packages or ():
yield pkg
for module in self.py_modules or ():
yield module
class CustomExtension(Extension):
def __init__(self, path):
self.path = path
super().__init__(pathlib.PurePath(path).name, [])
class build_CustomExtensions(build_ext):
def run(self):
for ext in (x for x in self.extensions if isinstance(x, CustomExtension)):
source = f"{ext.path}{suffix}"
build_dir = pathlib.PurePath(self.get_ext_fullpath(ext.name)).parent
os.makedirs(f"{build_dir}/{pathlib.PurePath(ext.path).parent}",
exist_ok = True)
shutil.copy(f"{source}", f"{build_dir}/{source}")
def find_extensions(directory):
extensions = []
for path, _, filenames in os.walk(directory):
for filename in filenames:
filename = pathlib.PurePath(filename)
if pathlib.PurePath(filename).suffix == suffix:
extensions.append(CustomExtension(os.path.join(path, filename.stem)))
return extensions
setup(
# Stuff
ext_modules = find_extensions("PackageRoot"),
cmdclass = {'build_ext': build_CustomExtensions}
distclass = CustomDistribution
)
I'm copying extensions into the build directory, and that's it. We override the distribution to lie to the egg-info writers about having any extensions, and everything is gravy.
Post a Comment for "Place Pre-compiled Extensions In Root Folder Of Non-pure Python Wheel Package"